7.1 상속 개념
상속은 부모가 자식에게 물려주는 행위를 말한다. 객체 지향 프로그램에서도 부모 클래스의 필드와 메소드를 자식 클래스에게 물려줄 수 있다.
상속은 잘 개발된 클래스를 재사용해서 새로운 클래스를 만들기 때문에 중복되는 코드를 줄여 시간 단축시킨다.
또 다른 이점으로는 클래스의 수정을 최소화할 수 있다는 것이다.
7.2 클래스 상속
프로그램에서는 자식이 부모를 선택한다. 자식 클래스를 선언할 때 어떤 부모로부터 상속받을 것인지를 결정하고, extends를 붙인다
public class 자식클래스 extends 부모클래스 {}
7.3 부모 생성자 호출.
부모 생성 후 자식 객체 생성이 가능하다.
public 자식클래스 extends 부모클래스 {
super(매개값, ... );
...
}
7.4 메소드 재정의.
부모 클래스의 모든 메소드가 자식 클래스에게 맞게 설계되어 있다면 가장 이상적인 상속이지만, 어떤 메소드는 자식 클래스가 사용하기에 적합하지 않을 수 있다. 이러한 메소드는 자식 클래스에서 재정의해서 사용해야 하며 이것을 메소드 오버라이딩이라고 한다.
메소드 오버라이딩
메소드가 오버라이딩되었다면 해당 부모 메소드는 숨겨지고, 자식 메소드가 우선적으로 사용된다.
부모 메소드의 선언부 (리턴 타입, 메소드 이름 , 매개변수)와 동일해야한다.
접근 제한을 더 강하게 오버라이딩 불가 ( public > private X )
새로운 예외를 throws 할 수 없다.
3.14159 보단 원주율 파이 상수 Math.PI를 사용하는 것이 보다 정밀하다. 자식 클래스인 Computer 클래스에서 메소드 오버라이딩해서 사용한다.
public class Calculator {
public double areaCircle(double r) {
System.out.println("Calculator 객체의 areaCircle() 실행");
return 3.14159 * r * r;
}
}
public class Computer extends Calculator {
@Override
public double areaCircle(double r) {
System.out.println("Computer 객체의 areaCircle() 실행");
return Math.PI * r * r;
}
}
public class ComputerExample {
public static void main(String[] args) {
int r = 10;
Calculator calc = new Calculator();
System.out.println("원 면적 : " + calc.areaCircle(r));
System.out.println();
Computer computer = new Computer();
System.out.println("원 면적 : " + computer.areaCircle(r));
}
}
부모 메소드 호출
메소드를 재정의하면, 부모 메소드는 숨겨지고 자식 메소드만 사용되기 때문에 비록 부모 메소드의 일부만 변경된다 하더라도 중복된 내용을 자식 메소드도 가지고 있어야한다.
예를 들어 부모 메소드가 100줄의 코드를 가지고 있을 경우, 자식 메소드에서 1줄만 추가하고 싶더라도 100줄의 코드를 자식 메소드에서 다시 작성해야 한다. 이 문제는 자식 메소드와 부모 메소드의 공동 작업 처리 기법을 이용하면 매우 쉽게 해결된다. 자식 메소드 내에서 부모 메소드를 호출하는 것인데, 다음과 같이 super 키워드와 도트연산자를 사용하면 숨겨진 부모 메소드를 호출한다.
![](https://velog.velcdn.com/images/namsm17/post/1b01d7d4-bf7c-4081-b2e3-da11bfdf3d37/image.jpeg)
7.5 final 클래스와 final 메소드
final 클래스
final 키워드를 class 앞에 붙이면 최종적인 클래스이므로 더 이상 상속이 불가능, 부모 클래스가 될 수 없다.
final 메소드
메소드 선언할 때 final 키워드를 붙이면 더 이상 오버라이딩이 불가능한 메소드가 된다. 상속받은 메소드는 재정의 할 수 없다.
public class Car {
public int speed;
public void speedUp() {
speed +=1;
}
public final void stop() {
System.out.println("차를 멈춤");
speed = 0;
}
}
public class SportsCar extends Car {
@Override
public void speedUp(){
speed+= 10;
}
}
7.6 protected 접근 제한자.
protected는 상속과 관련이 있으며, public과 default의 중간쯤에 해당하는 접근 제한을 한다.![](https://velog.velcdn.com/images/namsm17/post/74e14963-02ac-4d40-a30f-a0c6dcdd96a9/image.jpeg)
접근 제한자 | 제한 대상 | 제한 범위 |
---|
protected | 필드, 생성자, 메소드 | 같은 패키지이거나, 자식 객체만 사용 가능 |
7.7 타입 변환
클래스도 타입 변환이 있는데, 클래스의 타입 변환은 상속 관계에 있는 클래스 사이에서 발생한다.
자동 타입 변환
바로 위 부모가 아니더라도 상속 계층에서 상위 타입이라면 자동 타입 변환이 일어날 수 있고 부모 타입으로 자동 타입 변환된 이후에는 부모 클래스에 선언된 필드와 메소드만 접근이 가능하다. 비록 변수는 자식 객체를 참조하지만 변수로 접근 가능한 멤버는 부모 클래스 멤버로 한정된다. 그러나 자식 클래스에서 오버라이딩된 메소드가 있다면 부모 메소드 대신 오버라이딩된 메소드가 호출된다. 이것은 다형성과 관련있기 때문이다.
강제 타입 변환
자식 타입은 부모 타입으로 자동 변환되지만, 반대로 부모 타입은 자식 타입으로 자동 변환되지 않는다. (캐스팅 사용)
Parent parent = new Child();
Child child = (Child) parent;
자식 객체가 부모 타입으로 자동 변환하면 부모 타입에 선언된 필드와 메소드만 사용 가능하다는 제약 사항이 따르며 자식 타입에 선언된 필드와 메소드를 꼭 사용해야 한다면 강제 타입 변환을 해서 다시 자식 타입으로 변환해야 한다.
7.8 다형성
다형성이란 사용방법은 동일하지만 실행 결과가 다양하게 나오는 성질을 말한다.
다형성을 구현하기 위해서는 자동 타입 변환과 메소드 재정의가 필요하다.
필드 다형성
필드 다형성은 필드 타입은 동일하지만, 대입되는 객체가 달라져서 실행 결과가 다양하게 나올 수 있는 것을 말한다.
매개변수 다형성
다형성은 필드보다는 메소드를 호출할 때 많이 발생한다. 메소드가 클래스 타입의 매개변수를 가지고 있을 경우, 호출할 때 동일한 타입의 객체를 제공하는 것이 정석이지만 자식 객체를 제공할 수도 있다. 여기서 다형성이 발생한다.
7.9 객체 타입 확인
매개변수의 다형성에서 실제로 어떤 객체가 어떤 객체가 매개값으로 제공되었는지 확인하는 방법이 있다. 꼭 매개변수가 아니더라 변수가 참조하는 객체의 타입을 확인하고자 할 때, instanceeof연산자를 사용할 수 있다.
boolean result = 객체 instanceof 타입;
child 타입으로 강제 타입 변환하기 전에 매개값이 Child 타입인지 여부를 instanceof 연산자로 확인한다. Child타입이 아니라면 강제 타입 변환을 할 수 없기 때문이다. 강제 타입 변환을 하는 이유는 Child 객체의 모든 멤버(필드 메소드)에 접근하기 위해서이다.
public void method(Parent parent) {
if(parent instanceof Child) {
Child child = (Child) parent;
}
}
7.10 추상 클래스
사전적 의미로 추상은 실체 간에 공통되는 특성을 추출한 것을 말한다 곤충, 물고기 등의 공통점은 동물이다. 여기서 동물은 실체들의 공통되는 특성을 가지고 있는 추상적인 것이라고 볼 수 있다.
추상 클래스란?
객체를 생성할 수 있는 클래스를 실체 클래스라고 한다면, 이 클래스들의 공통적인 필드나 메소드를 추출해서 선언한 클래스를 추상 클래스라고 한다. 추상 클래스는 실체 클래스의 부모 역할을 한다. 따라서 실체 클래스는 추상 클래스를 상속해서 공통적인 필드나 메소드를 물려받을 수 있다.
추상 클래스 선언
abstract 키워드를 붙이면 추상 클래스 선언이 된다. 추상 클래스는 new 연산자를 이용해서 객체를 직접 만들지 못하고 상속을 통해 자식 클래스만 만들 수 있다.
public abstract class 클래스명 {
}
추상 클래스도 필드, 메소드 선언이 가능하다. 자식 객체가 생성될 때 super()로 추상 클래스의 생성자가 호출되기 때문에 생성자도 반드시 있어야 한다.
추상 메소드와 재정의
자식 클래스들이 가지고 있는 공통 메소드를 뽑아내어 추상 클래스로 작성할 때, 메소드 선언부(리턴 타입, 메소드명, 매개변수)만 동일하고 실행 내용은 자식 클래스마다 달라야 하는 경우가 많다.
7.11 봉인된 클래스
기본적으로 final 클래스를 제외한 모든 클래스는 부모 클래스가 될 수 있다. 그러나 Java 15부터는 무분별한 자식 클래스 생성을 방지하기 위해 봉인된 (sealed) 클래스가 도입되었다.
다음과 같이 Person의 자식 클래스는 Employee 와 Manager만 가능하고, 그 이외는 자식 클래스가 될 수 없도록 Person을 봉인된 클래스로 선언할 수 있다.
public sealed class Person permits Employee, Manager { ... }
sealed 키워드를 사용하면 permits 키워드 뒤에 상속 가능한 자식 클래스를 지정해야 한다. 봉인된 Person 클래스를 상속하는 Employee 와 Manager는 final 또는 non-sealed 키워드로 다음과 같이 선언하거나 , sealed 키워드를 사용해서 또 다른 봉인 클래스로 선언해야 한다.
public final class Employee extends Person { ... }
public non-sealed class Manager extends Person { ... }
확인문제
1. 1번
2. 2번
3. 1번
4. 4번
5. 2번
6. 부모 생성자를 제대로 x // Child 클래스에서 this.name=name; 라인을 지우고 super(name); 코드를 넣는다
7.
Parent(String nation) call
Parent() call
Child(String name) call
Child() call
8. 스노우 타이어가 굴러갑니다. X 2
9. 2번
10. work() 재정의 x , public abstract class Computer extends Machine { ... } 추상 클래스 선언
11. super
12. a instanceof C c