본문 바로가기

Language/Java

Overriding (오버라이딩) 과 Overloading (오버로딩)

Overloading 과 Overriding 의 차이는 구글링을 통해 어떤 차이가 있는지에 대한 설명은 쉽게 알 수 있었습니다. 

 

이번글은 그 둘을 왜 쓰는 지에 대해서 정리 해보려고 합니다. 둘의 사용 목적을 분명히 말할 수 없었고 앞으로는 객체지향적 관점에서 내가 사용하고 있는 코드들의 목적성을 분명하게 하는 것의 중요성을 깨달았기 때문입니다.


1. Overriding (오버라이딩)

public class Person {
	public void hello() {
		System.out.println("안녕하십니까");
	}
}
public class Student extends Person{
	public void hello() {
    	System.out.println("안녕하십니까 저는 학생입니다.");
    }
    public static void main(String [] args) {
		student.hello();
	}
}

 

오버라이딩의 경우 부모 클래스에 있는 메서드를 사용 할 때 그 메서드를 재정의 하는 것을 의미합니다. 

 

위의 예시 처럼 Person클래스에서 hello() 메서드는 "안녕하십니까"를 출력하는 메서드 인데 Student 클래스에서 hello() 메서드는 "안녕하십니까 저는 학생입니다." 를 출력하는 메서드로 재정의 되었습니다. 

 

오버라이딩은 재정의 하려는 메서드의 파라미터값을 변경해서도 안되고 이름을 변경해서도 안됩니다.  또한 부모 클래스의 메서드보다 자식 클래스의 메서드 접근제한이 동일 하거나 넓어야 합니다.

 

이말의 의미는 부모클래스의 메서드에 protected가 선언되었다면 자식 클래스에는 protected , public은 올 수 있지만 private나 default는 올수 없음을 의미합니다. 또한, 만약 부모 클래스의 메서드의 리턴 타입이 없다면 자식도 없어야 하고 리턴타입이 있다면 리턴타입이 자식과 부모가 동일 해야 합니다.

 

그럼 오버라이딩은 사용 하는 걸까요?

 

자식클래스가 부모클래스의 메서드를 상속 받아도 다른 기능을 사용하고자 하는 경우가 생기기 때문입니다. 예를 들어 Person이라는 클래스는를 상속받고 있는 Student 클래스는 Person 클래스의 내의 hello() 메서드와 다른 결과값을 얻기 위해 오버라이딩 해서 사용하는 경우가 있을 수 있습니다. 

 

물론 Student 클래스에 helloStudent() 라는 식으로 메서드를 새로 만들어 사용하는 것도 컴파일상에 문제는 전혀 되지 않지만 객체지향적 관점에서는 바람직 하지 않을 수 있습니다. 코드의 재사용성 능력이 떨어지기 때문이죠. 


2. Overloading (오버로딩) 

오버로딩은 메서드의 이름은 동일하지만 메서드에 전달하는 파라미터의 수는 달라야 하는게 원칙입니다. 오버라이딩 처럼 접근제한이나 리턴형은 어떻게 되어도 상관이 없고, 파라미터는 반드시 달라야 한다는게 둘의 차이점입니다.

 

그럼 오버로딩은  사용 하는 걸까요?

 

오버로딩을 사용하는 이유는 동일한 기능을 하는 메서드를 하나의 이름으로 처리할 수 있다는 특징 때문입니다.

 

예를 들어 println()은 int 타입이든 String 타입이든 동일한 기능을 제공하지만 타입에 따른 호출명이 다르다면 그 메소드를 사용하려는 입장에서는 함수 이름을 모두 알고 있어야 하기 때문에 굉장히 불편한 상황이 오게 됩니다. 

 

이러한 장점을 가장 잘 활용한 예시는 기본값 지정, 매개변수 자료형에 따른 다른 정의 두가지가 있습니다.   

 

먼저 '기본값 지정' 에 대한 사용 예시는 생성자가 있습니다.  

public class Student {
	private int age;
    	private String name;
	private String schoolName;
	
	public Student () {
		
	}
	public Student (int age, String name, String schoolName) {
		this.age = age;
		this.name = name;
		this.schoolName = schoolName;
	}
}

 

위의 코드에서 Student에 해당되는 생성자 두개가 있는데 하나는 default 생성자, 하나는 3개의 파라미터값을 받는 생성자가 존재 합니다. 각각 생성자의 이름은 동일하지만 전달받는 인자 값이 다르기 때문에 생성하게 되는 객체의 기본값을 다르게 지정할 수 있습니다. 

 

예를 들어 default 생성자인 경우에 기본값을 설정하지 않는게 되고 추후에 설정하겠다는 목적이 있고 두번째 생성자인 경우에는 객체를 생성하면서 기본 인자값을 전달 하겠다는 목적성이 있는 거죠.

 

다음으로는 '매개변수에 따른 다른 정의' 에 대한 예시를 들어 보겠습니다. 

public class Student {
	private int age;
    	private String name;
	private String schoolName;

	public void printInfo(int age, String name) {
		System.out.println("안녕하십니까 제 이름은 " + name + " 이고 제 나이는 " + age + "입니다.");
	}
	
	public void printInfo(int age, String name, String schoolName) {
		System.out.println("안녕하십니까 제 이름은 " + name + " 이고 제 나이는 " + age + "입니다. 현재 " + schoolName + " 학생입니다.");
	}
}

 

printInfo() 라는 두 메서드는 현재 오버로딩 된 상태인데 각각 전달받는 파라미터가 다릅니다. 각각의 메서드의 기능 첫번째는 학교이름은 제외하고 자신의 정보를 출력하고 두번째는 학교이름을 포함하여 자신의 정보를 출력합니다. 

 

이처럼 큰 틀에서는 같은 역할을 수행하지만 그 파라미터에 따라 그 메서드의 세부적인 기능을 다르게 정의할때 오버로딩을 사용합니다. 

정리하자면 오버로딩과 오버라이딩 모두 쓰는 목적이 분명 존재 하기 때문에 왜 쓰는지 정도는 알고 써야 할것 같습니다.

반응형

'Language > Java' 카테고리의 다른 글

Wrapper Class 란?  (0) 2022.01.07
static의 사용 이유와 스레드(thread)의 대한 개념  (0) 2022.01.06
Call by reference 와 Call by Value 차이  (0) 2022.01.05
클래스 (Class) 란?  (0) 2022.01.05
자바란?  (0) 2022.01.03