상속
- 부모 클래스에서는 기본 생성자를 만들어 놓는 것 이외에는 상속을 위해서 아무런 작업을 할 필요는 없다.
- 자식 클래스는 클래스 선언시 extends 다음에 부모 클래스 이름을 적어준다.
- 자식 클래스의 생성자가 호출되면, 자동으로 부모 클래스의 매개 변수 없는 생성자가 실행된다.
- 자식 클래스에서는 부모 클래스에 있는 public, protected로 선언된 모든 인스턴스 및 클래스 변수와 메소드를 사용할 수 있다.
상속의 필요성
자바에서는 부모 클래스가 갖고 있는 변수와 메소드를 상속받음으로써, 개발할 때 이중, 삼중의 일을 안해도 된다.
예를들어, 사람이라는 클래스를 학교에서 사용할 때, 기본적으로 이름, 전화번호는 공통으로 사용하지만 교수와 학생일 때 가질 수 있는 속성과 메소드가 다를 수 있다 이럴 때 공통적인 속성과 메소드를 사람이라는 클래스를 만들고, 학생과 교수라는 클래스를 사람 클래스를 상속받도록 하면 불필요한 코드를 줄일 수 있다.
자바에서는 다중 상속이 안 된다. "extends 뒤에 클래스를 하나만 써야지, 두 개 이상 클래스를 나열하면 컴파일이 되지 않는다."
상속과 생성자
- 부모 클래스에서는 기본 생성자를 만들어 놓는 것 이외에는 상속을 위해서 아무런 작업을 할 필요는 없다.
부모 클래스에서 기본 생성자를 만들지 않으면 에러가 발생하는데 이 때 해결 방법은 두가지가 있다.
- 부모 클래스에 "매개 변수가 없는" 기본 생성자를 만든다.
- 자식 클래스에서 부모 클래스의 생성자를 명시적으로 지정하는 super()를 사용한다.
자바에는 super라는 예약어가 있는데, super()를 사용하면 부모 클래스의 생성자를 호출한다는 것을 의미하고, super.printName()을 사용하면 부모 클래스에 있는 printName()이라는 메소드를 호출한다는 의미이다.
자바는 부모의 매개 변수가 없는 기본 생성자를 찾는 것이 기본이다. 그래서 부모 클래스에 매개 변수가 있는 생성자만 있을 경우에는 super()를 이용해서 부모 생성자를 꼭 호출해야만 한다.
오버라이딩
자식 클래스에서 부모 클래스에 있는 메소드와 동일하게 선언하는 것을 "메소드 Overriding"이라고 한다. 접근 제어자, 리턴 타입, 메소드 이름, 매개 변수 타입 및 개수가 모두 동일해야한다.
부모 클래스에 선언되어 있는 메소드와 동일하게 선언되어 있는 메소드를 자식 클래스에 선언하면 자식 클래스의 메소드만 실행된다.
ps. "동일하게 선언되어 있다"는 "동일한 시그니처(signature)를 가진다" 고 표현한다. 시그니처는 메소드 이름과 매개 변수의 타입 및 개수를 의미한다.
오버라이딩에 대해서 정리하면 다음과 같다.
- 메소드 오버라이딩은 부모 클래스의 메소드와 동일한 시그니처를 갖는 자식 클래스의 메소드가 존재할 때 성립된다.
- 오버라이딩된 메소드는 부모 클래스와 돌일한 리턴 타입을 가져야만 한다.
- 오버라이딩된 메소드의 접근 제어자는 부모 클래스에 있는 메소드와 달라도 되지만, 접근 권한이 확장되는 경우에만 혀용된다. 접근 권한이 축소될 경우에는 컴파일 에러가 발생한다.
참조 자료형의 형 변환
자식 클래스 타입에서 부모 클래스 타입으로 형변환을 하면 문제가 없고, 부모 클래스 타입에서 자식 클래스 타입으로 형 변환을 하면 에러가 발생한다.
- 참조 자료형도 형 변환이 가능하다.
- 자식 타입의 객체를 부모 타입으로 형 변환 하는 것은 자동으로 된다.
- 부모 타입의 객체를 자식 타입으로 형 변환을 할 때에는 명시적으로 타입을 지정해 주어야 한다. 이때, 부모 타입의 실제 객체는 자식 타입이어야만 한다.
- instanceof 예약어를 사용하면 객체의 타입을 확인할 수 있다.
- instanceof로 타입 확인을 할 때 부모 타입도 true라는 결과를 제공한다.
다형성(Polymorphism)
다형성을 이해하기 위해서는 위에서 정리한 오버라이딩과 형 변환을 이해해야 한다.
예를들어서, 하나의 부모 클래스에서 두 개의 자식 클래스를 만들었고 모두 오버라이딩된 printName을 가지고 있다고 했을 때.
Parent obj1 = new Parent();
Parent obj2 = new Child();
Parent obj3 = new OtherChild();
obj1.printName();
obj2.printName();
obj3.printName();
My Name is Parent
My Name is Child
My name is OtherChild
모든 객체의 타입이 Parent 타입으로 선언되어 있지만, printName()의 결과는 모두 다른 것을 볼 수 있다.
왜냐하면 각 객체의 실제 타입은 모두 다르기 때문이다. 이처럼 형 변환을 하더라도, 실제 호출되는 것은 원래 객체에 있는 메소드가 호출된다. 이것이 바로 다형성이다.
참고자료
자바의 神1 2nd Edition / 이상민 지음
'Java' 카테고리의 다른 글
[Java] 자바 컬렉션 Set (0) | 2022.01.11 |
---|---|
[Java] String 클래스 정리 (0) | 2022.01.08 |
[Java] 변수와 자료형 (0) | 2022.01.04 |
[Java] 자바 ArrayList 정리 (0) | 2021.09.16 |
[Java]정규표현식 정리 (0) | 2021.08.01 |