7.1 상속 개념
상속은 부모가 자식에게 물려주는 행위를 말함
OOP에서 부모클래스의 필드와 메소드를 자식클래스에게 물려줄 수 있다
장점 : 이미 개발된 클래스를 재사용 -> 중복코드 줄여 개발시간 단축한다
7.2 클래스 상속
자식클래스가 선언할 때 extends 부모클래스 형식으로 상속받는다
자바의 특징 : 다중 상속을 허용하지 않는다. 여러개의 부모클래스 상속 불가능
7.3 부모 생성자 호출
모든객체는 생성자 호출해야 한다( 부모객체든 자식객체든 )
부모객체가 생성되지 않았다면, 자식객체도 생성될 수 없다.
자식객체를 생성하면, 부모객체가 먼저 생성되고 그다음 자식객체가 생성된다
자식클래스 변수 = new 자식클래스();
위와같이 부모객체를 생성하지 않고 자식클래스의 객체를 생성하면, 자식객체는 생성되지 못해야한다
하지만 생성된다
-> 자식 생성자에 숨어있던 super(); 에 의해 부모생성자가 호출되기 때문이다
super() 는 컴파일 과정에서 자동으로 추가된다. (생략 가능)
주의 : 만약, 부모클래스의 기본생성자가 없고, 매개변수를 갖는 생성자만 있다고 한다면,
자식생성자 선언시 super(매개값,...) 을 직접 입력해야 한다. (생략 불가능)
7.4 메소드 재정의
이상 : 리스코프 치환 원칙 (LSP) : 자식 클래스는 부모 클래스의 기능을 온전히 수행해야한다?
현실 : 부모 클래스의 메소드가 자식클래스에 적합하지 않아 "수정"이 필요하다면
=> 메소드 오버라이딩 : 자식클래스에서 상속된 메소드를 제정의 한다 (자식 메소드가 우선적으로 사용됨)
주의할점 :
1. 부모메소드의 선언부(리턴타입, 메소드이름, 매개변수) 와 동일해야 한다
2. 접근제한 더 강하게 오버라이딩 할수 없다
3. 새로운 예외를 throws 할수 없다
@Overridie 어노테이션 :
생략가능 하지만, 컴파일시 정확하게 오버라이딩이 되었는지 체크해준다 (쓰자)
부모메소드 호출 :
오버라이딩을 할때
숨겨진 부모메소드를 호출해야한다면, 부모메소드의 코드를 다적어야 하지만
super.메소드명();
을 이용해서 숨겨진 부모메소드를 손쉽게 호출할 수 있다 (중복 제거)
7.5 final 클래스와 final 메소드
필드선언시 final 붙이면 초기값 설정 후 값을 변경할 수 없다
=> ? final붙은 필드값은 자식클래스에서 변경안되겟지??
클래스와 메소드에 final 붙이게 된다면 상속과 관련됨
final 클래스 :
클래스 선언시 final 붙이면 최종적인 클래스이므로, 상속 불가능한 클래스가 된다
-> final클래스는 부모클래스가 될 수 없어, 자식클래스를 만들 수 없다
final 메소드 :
메소드 선언시 final 붙이면 최종적인 메소드이므로, 오버라이딩 할수 없는 메소드가 된다
-> 상속할때, 자식클래스는 부모클래스에 선언된 final 메소드를 재정의(오버라이딩) 할수 없다.
7.6 protected 접근 제한자
private << default << protected << public
protected 접근제한자는
필드,생성자,메소드에 대하여 같은 패키지이거나, 자식객체만 사용가능하게 제한한다
7.7 타입 변환
타입 변환이란 타입을 다른 타입으로 변환하는 것을 말한다(기본타입 변환 앞에서 다룸)
클래스의 타입변환 : 상속관계에 있는 클래스 사이에서 발생한다
자동타입 변환 : 자동으로 타입변환 일어나는것
부모타입 변수 = 자식 타입 객체; // 작은것(오) -> 큰것(왼)
Cat cat = new Cat();
Animal animal = cat;
메모리상에서 cat(자식객체의 변수)과 anmal(부모객체의 변수)는 타입만 다를뿐(부모클래스/자식클래스)
동일한 Cat 객체를 참조한다 ( 자동 타입 변환 )
따라서 두 참조변수의 == 연산결과 true나온다
cat == animal // true
바로 위의 부모가 아니더라도, 상위 타입이라면 자동 타입 변환 가능함
부모타입으로 자동타입변환된 이후,
부모클래스에 선언된 필드와 메소드만 접근이 가능하다.
위에 말한 것 처럼, 변수는 자식객체를 참조하지만
변수로 접근가능한 멤버는 부모 클래스로 한정된다.
그러나
자식클래스에서 오버라이딩 된 메소드가 있다면,
부모 메소드 대신 오버라이딩 된 메소드가 호출된다..
(오버라이딩 - 자식메소드가 우선적으로 사용된다) ( 다형성과 관련된다 )
강제 타입 변환 (캐스팅,Casting)
자식타입 -> 부모타입 자동변환 가능하지만
부모타입 -> 자식타입 자동변환 불가능하다
'캐스팅 연산자'로 강제 타입 변환 할수있다
자식타입 변수 = (자식타입) 부모타입 객체; // 오(큰것) -> 왼(작은것) 강제 타입 변환
캐스팅연산자
다되는건 아니다
조건 :
자식 객체가 부모타입으로 자동타입변환 한 후 -> 다시 자식 타입으로 변환할 때, 강제타입 변환 가능하다
Parent parent = new Child(); // 자동타입변환
// -> 변수 parent 부모타입 필드 메소드만 사용할 수 있는 제약 있다
Child child = (Child) parent; // 강제타입변환
// -> 캐스팅 함으로써, 변수 child는 자식타입의 필드,메소드를 사용할 수 있게 되었다
위에 말한것처럼
자동타입변환 된 자식 객체는, 부모타입의 필드와 메소드만을 사용할 수 있다는 제약이 따랐다
만약, 자식타입에 선언된 필드와 메소드를 꼭 사용해야 한다면, 강제타입변환으로 다시 자식타입으로 변환해야 한다..
7.8 다형성
사용방법은 동일하지만, 실행결과가 다양하게 나오는 성질을 말한다..
자동차 부품을 교체하면 성능이 다르게 나오듯
객체를 교체하면 프로그램 실행 성능이 다르게 나올수 있게된다..
다형성을 구현하는 방법
위에서 언급한
자동타입변환 과 메소드 재정의( 오버라이딩 ) 을 통해 다형성을 구현한다
->
1. 자식 객체 1, 2 부모타입으로 자동타입변환한다 객체 1', 2'
(1 과 1'의 변수는 메모리상에서 같은 자식객체 1를 참조한다, 2 2'도 마찬가지)
2. 각 객체 1', 2' 에서 부모타입의 메소드 a를 재정의 한다( 오버라이딩 )
3. 부모타입의 객체 1' , 2' 가 메소드 a를 호출한다면 실행결과가 다르게 나오게 된다!
필드 다형성
필드 타입은 동일하지만, 대입되는 객체가 달라져서 실행 결과가 다양하게 나올 수 있는것을 말함
->
1. 위와 같은 상황이다
2. 부모클래스 선언시 필드 x 가 선언되어 있고, 메소드 a도 선언되어 있다
3. 메소드 a가 실행되면 -> 필드x가 메소드b를 호출한다
4. 자동타입변환된 객체 1', 2'가 메소드b를 재정의한다( 오버라이딩 )
5. 부모클래스의 객체를 생성한다 3
6. 3 과 1' 과 2' 가 각각 메소드 a를 실행한다
7. 3은 필드x가 재정의 전의 메소드 b를 호출한다 / 1' 와 2'는 필드x가 각자 재정의한 메소드b를 호출한다
8. 실행결과가 달라진다 -> 필드의 다형성
매개변수의 다형성
메소드가 클래스 타입의 매개변수를 가질 경우,
호출시 자식객체(자동타입변환된)를 매개변수로 줄 수 있다 -> 다형성
->
1. 클래스 A는 클래스 B를 매개변수로 가진다
2. 클래스 A는 클래스 B의 메소드x 를 호출한다
3. 클래스 B의 자식객체 b가 자동타입변환되어 부모의 타입을 가진다 -> b'
4. b'가 부모인 B의 메소드x를 재정의 한다.(오버라이딩)
5. 클래스 A의 매개변수(자동타입변환된 자식객체)에 따라 재정의된 메소드x를 호출하여 실행결과가 달라진다 -> 다형성
-> 자동타입 변환 없이, 메소드를 재정의한 자식 타입의 객체를 넣어도 가능한거같다..?
7.9 객체 타입 확인
매개변수의 다형성에서 실제로 어떤 객체가 매개값으로 제공되었는지 확인하는 방법
(매개변수가 아니더라도 변수가 참조하는 객체의 타입을 확인할 수 있음)
( 이놈이 메모리상 어떤 객체를 참조하는가 ?? )
instanceof 연산자를 이용한다!
boolean result = 객체 instanceof 타입;
// 좌항의 객체가 우항의 타입이라면 true, 그렇지 않다면 false를 반환한다
예) 강제타입변환(캐스팅)시 매개값이 자식객체타입인지 확인할 수 있다 , 자식객체타입이 아니라면 캐스팅 할수없기때문
public void method(Parent parent){
if(parent instanceof Child){ // 좌항의 변수가 우항의 타입과 같다면
Child child = (Child) parent; // 캐스팅 해라
}
}
7.10 추상 클래스
추상의 사전적 의미 : 실체 간의 공통되는 특성을 추출한것??
예를들어 새, 곤충, 물고기 등의 공통점은 동물이다, 동물은 실체들의 공통되는 특징을 가지고 있는 추상적인 것이다??
추상클래스란?
객체를 생성할 수 있는 클래스를 실체클래스
이 실체 클래스들의 공통적인 필드나 메소드를 추출해서 선언한 클래스를
추상클래스라고 한다
추상클래스는 실체클래스의 부모역할을 한다
특징 :
new 연산자를 통해 객체를 만들 수 없다, 실체클래스의 공통된 필드나 메소드를 추출해서 만들었기 때문
새로운 클래스를 만들기 위한 부모클래스로만 이용된다. -> extends 뒤에만 올수 있다
추상클래스 선언
클래스 선언에 abstract 키워드 붙이면 추상클래스 선언
public abstract class 클래스명{
//필드
//생성자
//메소드
}
new 연산자 통한 객체 생성 불가 / 상속을 통해 자식클래스만을 만들 수 있다
-> 생성자가 왜있어야 하는가?
자식객체가 생성될 때 super()로 추상클래스의 생성자가 호출되어야 하기 때문에
추상메소드와 재정의(오버라이드?)
자식클래스들이 가지는 공통 메소드를 뽑아내어 추상 클래스에서 작성할때,
추상 메소드는 메소드 선언부(리턴타입, 메소드명, 매개변수) 만 동일하고 실행내용이 자식클래스마다 달라야 할 경우가 많음
이런 경우 다음처럼 추상 매소드를 선언함 ( abstract가 붙고, 메소드 실행 내용인{} 가 없음)
abstract 리턴타입 메소드명(매개변수,...);
> 예시
public abstract class Animal{
abstract void sound();
}
추상메소드는, 메소드 실행부가 없기 때문에 자식클래스에서 반드시 오버라이딩으로 실행내용을 채워야함
7.11 봉인된 클래스
final 클래스를 제외한 모든 클래스는 부모클래스가 될 수 있다
java15 부터 봉인된(sealed) 클래스 도입됨
PASS