Java
[Java] 7. 상속
Empty_Bottle
2022. 6. 2. 15:18
7-1) 상속
- 이미 잘 개발된 클래스를 재사용해서 새로운 클래스를 만들기 때문에 중복되는 코드를 줄여준다.
- 부모 클래스의 수정으로 모든 자식 클래스들도 수정되는 효과를 통해 유지 보수 시간을 최소화할 수 있다.
- 클래스 상속
- 자식 클래스를 선언할 때 어떤 부모 클래스를 상속받을 것인지를 결정하고, 선택된 부모 클래스는 extends 뒤에 쓴다.
class 자식클래스 extends 부모클래스{
필드, 생성자, 메소드 등...
} - 자바에서의 상속 특징
① 여러 개의 부모 클래스를 상속할 수 없다. (상속 받을 수 있는 대상이 여럿이 아닌 하나.)
② 부모 클래스에서 private 접근 제한을 갖는 필드와 메소드는 상속 대상에서 제외된다.
③ 부모 클래스와 자식 클래스가 다른 패키지에 존재한다면 default 접근 제한을 갖는 필드와 메소드도 상속 대상에서 제외된다.
- 자식 클래스를 선언할 때 어떤 부모 클래스를 상속받을 것인지를 결정하고, 선택된 부모 클래스는 extends 뒤에 쓴다.
- 부모 생성자 호출
- 부모 생성자는 자식 생성자의 맨 첫 줄에서 호출된다.
- super()은 부모의 기본 생성자를 호출.
- super(매개값, … )은 매개값의 타입과 일치하는 부모 생성자를 호출한다.
- 매개값의 타입과 일치하는 부모 생성자가 없을 경우 컴파일러 에러가 발생한다. - super(매개값, … )이 생략된 경우 컴파일러에 의해 super()가 자동으로 추가되기 때문에 부모의 기본 생성자가 반드시 존재해야 한다.
- 메소드 재정의
- 부모 클래스의 메소드 중 자식 클래스가 사용하기에 적합하지 않은 메소드의 경우 상속된 일부 메소드를 자식 클래스에서 다시 수정해서 사용하는 기능. (=Overriding)
- 메소드 재정의 방법
- 부모의 메소드와 동일한 시그너처(리턴 타입, 메소드 이름, 매개 변수 목록)를 가져야 한다.
- 접근 제한을 더 강하게 재정의할 수 없다.
- 새로운 예외(Exception)를 throws할 수 없다.. - 부모 메소드 호출
- 메소드가 재정의되었다면 부모 객체의 메소드는 숨겨지기 때문에 자식 객체에서 메소드를 호출하면 재정의된 자식 메소드가 호출된다.
- 자식 클래스 내부에서 재정의된 부모 클래스의 메소드를 호출해야 하는 상황이 발생하면 명시적으로 super 키워드를 붙여서 부모 메소드를 호출할 수 있다. ( ≫ super.부모메소드(); )
- final 클래스와 final 메소드
- final 키워드는 어떤 대상에 사용하느냐에 따라 해석이 조금씩 달라지지만 해당 선언이 최종 상태이고 결코 수정될 수 없음을 의미한다.
- final 클래스: 해당 클래스는 최종적인 클래스이므로 상속할 수 없는 클래스.
- final 메소드: 해당 메소드는 최종적인 메소드이므로 부모 클래스를 상속하여 자식 클래스를 선언할 때 자식클래스에서 해당 메소드를 재정의(Overriding)할 수 없음을 의미.
- final 키워드는 어떤 대상에 사용하느냐에 따라 해석이 조금씩 달라지지만 해당 선언이 최종 상태이고 결코 수정될 수 없음을 의미한다.
7-2) 타입 변환과 다형성
- 다형성: 사용 방법은 동일하지만 다양한 객체를 이용하여 다양한 실행 결과가 나오도록 하는 성질.
- 자동 타입 변환
- 타입을 다른 타입으로 변환하는 행위.
- 클래스의 변환은 상속 관계에 있는 클래스 사이에서 발생.
- 자식은 부모 타입으로 자동 타입 변환이 가능. - 자동 타입 변환: 프로그램 실행 도중에 자동적으로 타입 변환이 일어나는 것
≫ 부모타입 변수 = 자식타입;
- 자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급될 수 있다.
- 부모 타입으로 자동 타입 변환된 이후에는 부모 클래스에 선언된 필드와 메소드만 접근이 가능.
- 변수는 자식 객체를 참조하지만 변수로 접근 가능한 멤버는 부모 클래스 멤버로만 한정된다.
⇒예외로 메소드가 자식 클래스에서 재정의되었다면 자식 클래스의 메소드가 대신 호출된다.
- 필드의 다형성
- 필드의 타입을 부모 타입으로,,, P.337~350까지 1도 몰으갯읍니다 머,,, 어쩌갯읍니까 제가 멍청이지요,,,
- 매개 변수의 다형성
- 메소드를 호출할 때에는 매개 변수의 타입과 동일한 매개값을 지정하는 것이 정석이지만 매개값을 다양화하기 위해 매개 변수에 자식 객체를 지정할 수도 있다.
- 하핫 여기도 전혀 몰으갯는 걸~~~!~!~~!~!
- 매개 변수의 타입이 클래스일 경우, 해당 클래스의 객체뿐만 아니라 자식 객체까지도 매개값으로 사용할 수 있다. (가 매우 중요한 것이라는데 무슨 말인지 이해가 되지 않는 나, 제법 멍청해요.)
- 강제 타입 변환
- 부모 타입을 자식 타입으로 변환하는 것.
- 자식 타입이 부모 타입으로 자동 변환한 후 다시 자식 타입으로 변환할 때 강제 타입 변환 사용 가능.
- 자식 타입이 부모 타입으로 자동 타입 변환하면 부모에 선언된 필드와 메소드만 사용 가능한 제약 사항이 따름.
- 자동 타입 변환된 상태에서 자식에 선언된 필드와 메소드를 꼭 사용해야 한다면 강제 타입 변환을 해서 다시 자식 타입으로 변환한 후 자식의 필드와 메소드를 사용한다.
- 객체 타입 확인
- 부모 변수가 참조하는 객체가 부모 객체인지 자식 객체인지 확인하는 방법으로 instanceof 연산자를 사용한다.
≫ boolean result = 좌항(객체) instanceof 우항(타입)
: 좌항이 우항의 타입으로 변환이 가능한지 확인하는 연산자로 가능하면 true를, 불가하면 false를 반환한다.(?)
- 부모 변수가 참조하는 객체가 부모 객체인지 자식 객체인지 확인하는 방법으로 instanceof 연산자를 사용한다.
7-3) 추상 클래스
- 객체를 직접 생성할 수 있는 클래스를 실체 클래스라고 할 때 실체 클래스들의 공통적인 특성을 추출해서 선언한 클래스를 추상 클래스라고 한다. - 추상 클래스가 부모, 실체 클래스가 자식으로 구현되어 실체 클래스는 추상 클래스의 모든 특성을 물려받고, 추가적인 특성을 가질 수 있다.* 특성: 필드와 메소드
- 추상 클래스의 용도
① 공통된 필드와 메소드의 이름을 통일할 목적: 실체 클래스를 설계하는 사람이 여러 사람일 경우 데이터와 기능이 동일하지만 사람마다 각기 다른 이름으로 필드와 메소드를 설정하는 것을 방지할 수 있다.
② 실체 클래스를 작성할 때 시간 절약:공통적인 필드와 메소드는 추상 클래스에 모두 선언해두고 다른 점만 실체 클래스에 선언하면 실체 클래스를 작성하는 데 시간을 절약할 수 있다. - 추상 클래스 선언
- 클래스 선언에 abstract 키워드를 붙여 선언한다.
≫ public abstract class 클래스명{
필드, 생성자, 메소드
}
- abstract를 붙이면 new 연산자를 사용하여 객체를 만들지 못하고 상속을 통해 자식 클래스만 만들 수 있다.
- 일반 클래스와 마찬가지로 필드, 생성자, 메소드 선언을 할 수 있다.
- new 연산자로 직접 생성자를 호출할 수는 없지만 자식 객체가 생성될 때 super(…)를 호출하여 추상 클래스 객체를 생성하므로 추상 클래스도 생성자가 반드시 있어야 한다. - 추상 클래스는 새로운 실체 클래스를 만들기 위해 부모 클래스로만 사용된다.
- 클래스 선언에 abstract 키워드를 붙여 선언한다.
- 추상 메소드와 재정의
- 추상 클래스는 실체 클래스가 공통적으로 가져야 할 필드와 메소드들을 정의해놓은 추상적인 클래스로, 실체 클래스의 멤버(필드, 메소드)를 통일하는 데 목적이 있다.
- 메소드의 선언만 통일하고 실행 내용은 실체 클래스마다 달라야 하는 경우에 추상 클래스는 추상 메소드를 선언할 수 있다. (아마도 동작(ex. 동물이 울다)은 같은데 내용(ex. 울음 소리)가 다른 케이스를 말하는 듯.)
≫[public | protected] abstract 리턴타입 메소드이름(매개변수, … ); - 추상 클래스 설계 시 하위 클래스가 반드시 실행 내용을 채우도록 강제하고 싶은 메소드가 있을 경우 해당 메소드를 추상 메소드로 선언한다.
=> 자식 클래스는 반드시 추상 메소드를 재정의해서 실행 내용을 작성해야 하는데 그렇지 않으면 컴파일 에러 발생.