이 둘은 클래스의 인스턴스 멤버인 메소드를 재정의 또는 확장의 개념이다!
load = 올린다
overload = 중첩해서 계속 올렸다
같은 이름의 메소드를 여러 개 정의하는 것 = 메소드 중복정의
같은 클래스 내부에서 메소드를 확장하기 위한 개념이다.
메소드의 이름이 같으면 에러가 나야하지만 특정조건을 만족한다면 같은 이름으로 여러 개 메소드를 정의할 수 있게 허용한다
1) 똑같은 이름의 메소드
2) 매개변수의 자료형 또는 개수 또는 순서가 달라야한다. (하나라도 다르면 만들어짐)
3) 메소드의 return 타입이 달라야 함
1) 생성자(기본값 지정)
class Student {
private int age;
private String name;
private String schoolName;
//defalut 생성자
public StudentInfo () {
}
//3개의 파라미터값 생성자
public StudentInfo (int age, String name, String schoolName) {
this.age = age;
this.name = name;
this.schoolName = schoolName;
}
}
위의 예시를 보면 StudentInfo에 해당되는 생성자 두개가 있다. 하나는 default 생성자, 하나는 3개의 파라미터값을 받는 생성자가 존재한다.
각각 전달받는 인자 값이 다르기 때문에 생성하게 되는 객체의 기본값을 다르게 지정할 수 있au 생성자의 이름은 동일하게 설정할 수 있다.
예를 들어 default 생성자인 경우에 기본값을 설정하지 않고 추후에 설정하겠다는 목적이 있다. 두번째 생성자인 경우에는 객체를 생성하면서 기본 인자값을 전달 하겠다는 목적성이 있다.
2) 상이한 파라미터
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() 라는 두 메서드는 현재 오버로딩 된 상태인데 각각 전달받는 파라미터가 다르다.
첫번째는 학교이름은 제외하고 Student의 정보를 출력하고 두번째는 학교이름까지 포함하여 자신의 정보를 출력한다.
이처럼 큰 틀에서는 같은 역할을 수행하지만 그 파라미터에 따라 그 메서드의 세부적인 기능을 다르게 정의할때 오버로딩을 사용한다.
동일한 기능을 하는 메서드를 하나의 이름으로 처리할 수 있는 경제적인 이유가 있다.
예를들어, println() 메서드는 오버로딩 되어있기 때문에 int형 인자, String형 인자, boolean형 인자, char형 인자 모두 받아서 동작할 수 있다.
만약 오버로딩이 없다면 int형 인자를 받는 메서드는 printlnInt()로 String형 인자를 받는 메서드는 printlnString()으로 boolean형 인자를 받는 메서드는 printlnBoolean()등으로 각각의 메서드 이름을 따로 만들어줘야 한다.
또한 타입에 따른 호출명이 다르다면 그 메소드를 사용하려면 타입과 함수 이름을 모두 알고 있어야 하기 때문에 불편함이 생긴다.
따라서 오버로딩이 있기 때문에 같은 기능을 하는 메서드를 하나의 이름인 println()으로 사용할 수 있게 된다.
자식클래스가 부모 클래스에 있는 메서드를 사용 할 때 그 메서드를 재정의 하는 것을 말한다.
1) 재정의 하려는 메서드의 파라미터값을 변경해서도 안되고 이름을 변경해서도 안된다.
2) 부모 클래스의 메서드보다 자식 클래스의 메서드 접근제한이 동일 하거나 넓어야 한다.
ex) 부모클래스의 메서드에 protected가 선언되었다면,
자식 클래스의 메서드에는 private나 default는 올수 없다. protected , public만 가능하다.
👀 접근 제한자에 대해 모르겠다면? [접근제한자 설명 링크]
3) 부모클래스의 리턴타입과 자식클래스의 리턴타입이 같아야 한다.
부모 클래스의 메서드의 리턴타입이 없다면 자식도 없어야 하고 리턴타입이 있다면 리터타입이 자식과 부모가 동일 해야 한다.
즉, 리턴타입, 메소드 이름, 매개변수가 동일해야한다.
//부모 클래스
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() 메서드는 "안녕하시렵니까 저는 직딩입니다." 를 출력하는 메서드로 재정의 되었다. 같은 메소드명을 사용하지만 출력되는 값이 상이하다.
위에서 설명했듯이 오버라이딩은 재정의 하려는 메서드의 파라미터값을 변경해서도 안되고 파라미터의 이름을 변경해서도 안된다.(hello라는 메서드)
또한 만약 부모 클래스의 메서드의 리턴타입이 없기 때문에 자식도 리턴타입이 없다. 만약 부모 클래스의 메서드에서 리턴타입이 있다면 자식 또한 리터타입이 부모와 동일 해야 한다.
프로그래밍을 하면서 부모 클래스와 자식 클래스 모두 동일한 메서드 명을 사용해야 될 경우가 존재하는데, 자식 클래스 입장에서는 부모 클래스와 다른 결과물을 보여주고 싶을 때가 있다.
이때 오버라이딩을 사용한다.
예를 들어 Person이라는 클래스는를 상속받고 있는 Student 클래스는 Person 클래스의 내의 hello() 메서드와 다른 결과값을 얻기 위해 오버라이딩 해서 사용하는 경우가 있다.
물론 Student 클래스에 새로운 메소드를 만들어 사용하는 것도(예를 들어, helloStudent()) 컴파일상에 문제는 전혀 되지 않는다. 하지만 객체지향프로그래밍(OOP 적 관점)에서는 코드의 재사용성이 떨어지기 때문에 바람직하지 않을 수 있다.
참고자료
1) https://jminc00.tistory.com/9
2) https://wildeveloperetrain.tistory.com/110
3) 사진
https://www.zerocho.com/category/JavaScript/post/59c17a58f40d2800197c65d6
4) https://jforj.tistory.com/16?category=826554