Java 6일차
상속
개념
- 부모 클래스(상위 클래스)의 멤버를 자식 클래스(하위 클래스)에 물려주는 것
- 이미 잘 개발된 클래스를 재사용해서 새로운 클래스 생성 ⇒ 코드 중복 줄여줌
- 부모 클래스에서 private 접근 제한자를 갖는 필드와 메소드는 상속 대상에서 제외
- 부모 클래스와 자식 클래스가 다른 패키지에 존재한다면 default 접근 제한을 갖는 필드와 메소드도 상속 대상에서 제외
- 클래스 수정 최소화, 유지보수 시간 최소화
클래스 상속
-
자식 클래스를 선언하고 extends 뒤에 상속 받을 부모 클래스 명시
class 자식클래스 extends 부모클래스 { }
-
자바는 다중상속을 허용하지 않음
- 여러 개의 부모 클래스를 상속할 수 없음
부모 생성자 호출
- 자식 객체를 생성하면 부모 객체가 먼저 생성되고 자식 객체가 그 다음에 생성
- 모든 객체는 클래스의 생성자를 호출해야만 생성됨
-
super()
: 생성자가 명시적으로 선언되지 않았을 때 부모의 기본 생성자 호출. 컴파일러가 생성
-
- 부모 클래스에 기본 생성자가 없고 매개 변수가 있는 생성자만 있다면 자식 생성자에서 반드시 부모 생성자 호출을 위해
super(매개값)
명시적으로 호출- 반드시 자식 생성자 첫 줄에 위치
메소드 재정의
오버라이딩
- 상속된 메소드의 내용이 자식 클래스에 맞지 않을 경우, 자식 클래스에서 동일한 메소드 재정의
- 메소드가 오버라이딩 되면 부모 객체의 메소드 숨겨져 자식 객체에서 메소드 호출하면 오버라이딩 된 자식 메소드 호출
- 메소드 오버라이딩 규칙
- 부모의 메소드와 동일한 시그니처(리턴 타입, 메소드 이름, 매개 변수 리스트) 가져야 함
- 접근 제한을 더 강하게 오버라이딩할 수 없음
- 새로운 예외(Exception)를 throws할 수 없음
부모 메소드 호출(super)
- 자식 클래스 내부에서 오버라이딩된 부모 클래스의 메소드를 호출해야 하는 상황 ⇒ super 키워드로 부모 메소드 호출
final 클래스와 final 메소드
상속할 수 없는 final 클래스
- final 키워드는 최종적이라는 뜻 ⇒ 상속할 수 없음
- 자식 클래스 만들 수 없음
오버라이딩할 수 없는 final 메소드
- 부모 클래스에 선언된 final 메소드를 자식 클래스에서 오버라이딩 불가
protected 접근 제한자
- public과 default 접근 제한의 중간
- 같은 패키지에서는 default 처럼 접근 제한이 없지만, 다른 패키지에서는 자식 클래스만 접근 허용
- 필드, 생성자, 메소드 선언에 사용
타입 변환과 다형성
다형성
- 같은 타입이지만 실행 결과가 다양한 객체를 이용할 수 있는 성질
- 하나의 타입에 여러 객체를 대입해서 다양한 기능을 이용할 수 있도록 함
- 다형성 위해 부모 클래스로 타입 변환 허용 ⇒ 객체의 부품화
자동 타입 변환
- 프로그램 실행 도중 자동으로 타입 변환
- 자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급될 수 있음
- 바로 위의 부모가 아니더라도 상속 계층에서 상위 타입이면 자동 타입 변환이 일어날 수 있음
- 부모 타입으로 자동 타입 변환 ⇒ 부모 클래스에서 선언된 필드와 메소드만 접근 가능
- 메소드가 자식 클래스에서 오버라이딩 되었다면 자식 클래스의 메소드가 대신 호출 ⇒ 다형성
필드의 다형성
- 필드 값을 다양화함으로써 실행 결과가 다르게 나오도록 구현
- 필드 타입은 변함 없지만 실행 도중에 어떤 객체를 필드로 저장하느냐에 따라 실행 결과 달라질 수 있음
하나의 배열로 객체 관리
class Car {
Tire frontLeftTire = new Tire("앞왼쪽", 6);
Tire frontRightTire = new Tire("앞오른쪽", 2);
Tire backLeftTire = new Tire("뒤왼쪽", 3);
Tire backRightTire = new Tire("뒤오른쪽", 4);
}
class Car {
Tire[] tires = {
new Tire("앞왼쪽", 6)),
new Tire("앞오른쪽", 2),
new Tire("뒤왼쪽", 3),
new Tire("뒤오른쪽", 4)
}
}
-
tires[1] = new KumhoTire("앞오른쪽", 13);
- tires 배열의 각 항목은 Tire 타입이므로 자식 객체인 KumhoTire를 대입하면 자동 타입 변환이 발생하기 때문에 아무런 문제 없음
매개 변수의 다형성
- 자동 타입 변환은 필드의 값을 대입할 때에도 발생하지만 메소드 호출할 때 많이 발생
- 메소드 호출 시 매개 변수의 타입과 동일한 매개값을 지정하는 것이 정석
- 매개값을 다양화하기 위해 매개 변수에 자식 타입 객체를 지정할 수도 있음
- 매개 변수의 타입이 클래스일 경우, 해당 클래스의 객체 뿐만 아니라 자식 객체까지 매개값으로 사용할 수 있음
강제 타입 변환
- 부모 타입을 자식 타입으로 변환하는 것
- 모든 부모 타입을 자식 클래스 타입으로 강제 변환할 수 있는 것은 아님
- 자식 타입이 부모 타입으로 자동 변환한 후, 다시 자식 타입으로 변환할 때 강제 타입 변환 사용
- 자식 타입이 부모 타입으로 자동 변환하면, 부모 타입에 선언된 필드와 메소드만 사용 가능
- 자식 타입에 선언된 필드와 메소드를 꼭 사용해야 한다면 강제 타입 변환으로 자식 타입으로 변환 후 자식 타입의 필드와 메소드 사용
객체 타입 확인
-
instanceof 연산자로 어떤 객체가 어떤 클래스의 인스턴스인지 확인
boolean result = 객체 instanceof 타입 // 객체가 해당 타입으로 생성됐으면 true, 아니면 false 반환
추상 클래스
개념
- 클래스들의 공통적인 특성을 추출해서 선언한 클래스
- 추상 클래스(부모)와 실체 클래스(자식)는 상속의 관계
- 추상 클래스는 객체를 직접 생성해서 사용할 수 없음 ⇒ new 연산자를 사용해서 인스턴스 생성하지 못함
- extends 뒤에만 올 수 있는 클래스
용도
- 실체 클래스들의 공통된 필드와 메소드의 이름을 통일
- 실체 클래스를 작성할 때 시간 절약
선언
public abstract class 클래스 {
// 필드
// 생성자
// 메소드
}
- abstract 키워드 사용
- 상속을 통해 자식 클래스를 만들 수 있음
- 일반 클래스와 마찬가지로 필드, 생성자, 메소드 선언
추상 메소드와 오버라이딩
- 추상 메소드는 추상 클래스에서만 선언 가능
- 메소드 선언부만 있고 실행 내용인 중괄호가 없는 메소드
- 하위 메소드가 반드시 실행 내용을 채우도록 강요하고 싶은 메소드가 있을 경우 사용
- 자식 클래스는 반드시 추상 메소드를 재정의(오버라이딩) 해서 실행 내용 작성해야 함