상속 개념
부모 클래스의 멤버를 자식 클래스에게 물려주는 행위, 이때 부모 클래스를 상위 클래스라고 부르기도 하며,
자식 클래스를하위 클래스, 또는 파생 클래스라고 부른다.
상속은 이미 잘 개발된 클래스를 재 사용해서 새로운 클래스를 만들기 때문에 코드의 중복을 줄여준다.
public class A{
int field;
void method1(){}
}
public class B extends A{
String field2;
void method2(){}
}
부모 클래스에서 private접근 제한을 갖는 필드와 메소드는 상속대상에서 제외된다.
부모 클래스와 자식클래스가 다른 패키지에 존재한다면 default 접근 제한을 갖는 필드와 메소드도 상속 대상에서 제외된다.
클래스의 상속
class 자식클래스 extends 부모클래스{
}
다른 언어와 달리 자바는 다중 상속을 허용하지 않는다.
부모 생성자 호출
부모 객체가 먼저 생성되고 자식 객체가 그 다음에 생성된다.
모든 객체는 클래스의 생성자를 호출해야만 생성된다.
부모 생성자는 어디서 호출? → 부모 생성자는 자식 생성자의 맨 첫줄에서 호출된다
자식클래스에서 부모클래스에 대한 생성자가 명시적으로 선언되지 않앗다면 아래와 같이 기본생성자를 생성한다.
여기서 super()는 부모클래스(A)의 생성자를 호출한다.
public class B{
public B(){
super();
}
}
<직접 자식 생성자를 선언하고 명시적으로 부모 생성자를 호출하고 싶을때>
자식 클래스(매개변수 선언, ...){
super(매개값, ...);
}
매소드 재정의@Override
부모 클래스의 모든 메소드가 자식 클래스에 맞게 설계 되어 있다면 가장 이상적인 상속이지만,
어떤 메소드는 자식 클래스가 사용하기에 적합하지 않을 수 있다.
이 경우 상속된 일부 메소드는 자식 클래스에서다시 수정해서 사용해야하고,
자바는 이런 경우를 위해 Override기능을 제공한다.
메소드가 오버라이딩되었다면 부모 객체의 메소드는 숨겨지기 때문에,
자식 객체에서 메소드를 호출하면 오버라이딩된 자식 메소드가 호출된다.
메소드 오버라이딩할때 주의할점
- 부모의 메소드와 동일한 시그너처를 가져야 한다.
- 접근 제한을 더 강하게 오버라이딩 할 수 없다.
→부모 메소드가 public 접근 제한을 가지고 있을 경우 오버라이딩 하는 자식 메소드는 default나 private로 수정할 수 없다는 뜻 - ⚠️ 즉 부모의 접근제한자 보다 상위로는 오버라이딩이 가능하다. **public → protected → default → private**
- 새로운 예외(Exception)를 throws할 수 없다.
부모메소드 호출
자식 클래스에서 부모 클래스의 메소드를 오버라이딩하게되면, 부모 클래스의 메소드는 숨겨지고
오버라이딩된 자식메소드만 사용된다. 그러나 자식 클래스 내부에서 오버라이딩된 부모 클래스의 메소드를 호출해야
하는 상황이 발생한다면 명시적으로 super키워드를 붙여서 부모 메소드를 호출할 수 있다.
final 클래스와 final 메소드
필드 선언 시에 final이 지정되면 초기값 설정 후 더이상 변경할 수 없다.
클래스를 선언할 때 final 키워드를 class앞에 붙이게 되면 이 클래스는 최종적인 클래스이므로 상속 할 수 없는 클래스가 된다.
→ 부모 클래스가 될 수 없어 자식 클래스를 만들 수 없다는 것이다.
public final class 클래스{
...
}
오버라이딩할 수 없는 final 메소드
메소드를 선언할때 final 키워드를 붙이게 되면 이 메소드는 최종적인 메소드이므로 오버라이딩할 수 없는 메소드가 된다.
즉 부모 클래스를 상속해서 자식 클래스를 선언할 때 부모 클래스에 선언된 final 메소드는 자식 클래스에서 재정의할 수 없다는것이다.
public final void mehtod(){
...
}
Protected 접근 제한자
protceted는 public과 default 접근 제한의 중간쯤에 해당한다.
같은 페키지에서는 default와 같이 접근 제한이 없지만 다른 패키지에서는 자식 클래스만 접근을 허용한다.
package chap7;
public class A {
protected String name;
}
package chap7;
public class SampleCode {
public void method(){
A a = new A();
a.name= "abcd";
}
}
package chap7.anotherpackage;
import chap7.A;
public class someClass {
public void method(){
A a = new A();
a.name;(x)
}
}
package chap7.anotherpackage;
import chap7.A;
public class ChildClass extends A {
public void method() {
this.name = "";
}
}
타입 변환과 다형성
다형성은 같은 타입이지만 실행 결과가 다양한 객체를 이용할 수 있는 성질을 말한다.
다형성을 위해 자바는 부모 클래스로 타입 변환을 허용한다. 즉 부모 타입에 모든 자식 객체가 대입될 수 있다.
public class Car{
Tire t1 = new HankookTire();
Tire t2 = new KumhoTire();
}
Tire를 상속했기 때문에 Tire변수에 HankookTire,KumhoTire를 대입할 수 있다.
자동 타입 변환
프로그램 실행 도중에 자동적으로 타입 변환이 일어나는것을 말한다.
Cat cat = new Cat();
Animal animal = cat;
animal 변수가 Animal타입이므로 부모인 Animal 객체를 참조하는 것이 맞지 않느냐고 생각 할 수 있지만,
cat과 animal둘다 같은 Cat객체를 참조하고 있다.
부모 타입으로 자동 타입 변환된 이후에는 부모 클래스에 선언된 필드와 메소드만 접근이 가능하다.
class Parent{
void method1(){}
void method2(){}
}
class Child extends Parent{
@Override
void method2(){}
void method3(){}
}
class ChildExample{
public static void main(String[] args){
Child child = new Child();
Parent parent = child;
parent.method1(); // Parent의 method1
parent.method2(); //child의 method2
parent.method3(); // 호출 불가
}
}
필드의 다형성
필드의 타입은 변함이 없지만, 실행 도중에 어떤 객체를 필드로 저장하느냐에 따라 실행 결과가 달라질 수 있는것
프로그램은 수많은 객체들이 서로 연결되고 각자의 역할을 하게 되는데, 이 객체들은 다른 객체로 교체될 수 있어야 한다.
public class Car{
Tire frontLeftTire = new Tire("앞 왼쪽", 6)
Tire frontRightTire = new Tire("앞 오른쪽", 2)
Tire backLeftTire = new Tire("뒤 왼쪽", 3)
Tire backRightTire = new Tire("뒤 오른쪽", 4)
int run(){
System.out.println("자동차가 달립니다.")
if(frontLeftTire.roll() == false){stop(); return 1;}
if(frontRightTire.roll() == false){stop(); return 2;}
if(backLeftTire.roll() == false){stop(); return 3;}
if(backRightTire.roll() == false){stop(); return 4;}
}
void stop(){
System.out.println("자동차가 멈춥니다.")
}
}
public class HankookTire extends Tire{
@Override
public boolean roll(){
//roll 재정의
}
}
public class KumhoTire extends Tire{
@Override
public boolean roll(){
//roll 재정의
}
}
public class carExample{
public static void main(String[] args){
Car car = new Car();
for(int i =1; i < 5; i ++){
int problemLocation = car.run()
}
switch(problemLocation){
case 1:
car.frontLeftTire = new HankookTire("앞 왼쪽", 15);
case 2:
.....
}
}
}
매개 변수의 다형성
자동 타입 변환은 필드의 값을 대입할 때에도 발생하지만, 주로 메소드를 호출할 때 많이 발생한다.
메소드를 호출할 때에는 매개 변수의 타입과 동일한 매개값을 지정하는 것이 정석이지만, 매개값을 다양화 하기 위해
매개 변수에 자식 타입 객체를 지정할 수도 있다.
class Driver{
void drive(Vehicle vehicle){
vehicle.run();
}
}
Driver driver = new Driver();
Bus bus = new Bus();
driver.drive(bus);
*Vehicle vehicle = bus; //자동 타입 변환
강제 타입 변환(Casting)
강제 타입 변환은 부모 타입을 자식 타입으로 변환하는 것을 말한다.
자식 타입이 부모 타입으로 자동 변환한 후, 다시 자식 타입으로 변환할 때 강제 타입 변환을 사용할 수 있다.
public ChildExample{
//psvm
Parent parent = new Child();
parent.field2 = "yyy" 불가능
Child child = (Child)parent;
child.field2 = "yyy"가능
}
class Parent{
String field1;
void method1(){}
void method2(){}
}
class Child extends Parent{
String field2;
void method3(){}
}
객체 타입 확인(instanceof)
어떤 객체가 어떤 클래스의 인스턴스인지 확인하려면 instanceof 연산자를 사용할 수 있다.
좌향의 객체가 우향의 인스턴스이면 즉 우항의 타입으로 객체가 생성되었으면 true를 산출한다.
boolean result = 좌항(객체) instanceof 우항(타입)
메소드 내에서 강제 타입 변환이 필요할 경우 instanceof 연산자로 확인하고 강제 변환을 해야 한다.
public void method(Parent parent){
if(parent instanceof Child){
Child child = (Child)parent;
}
}
추상 클래스
객체를 직접 생성할 수 있는 클래스를 실체 클래스라고 한다면 이 클래스들의 공통적인 특성을 추출해서 선언한 클래스를
추상 클래스라고 한다. 추상 클래스와 실체 클래스는 상속의 관계를 가지고 있다.
추상 클래스는 실체 클래스의 공통되는 필드와 메소드를 추출해서 만들었기 때문에 객체를 직접 생성해서 사용할수 없다
Animal animal = new Animal(); ----x
class Ant extends Animal{} -----o
용도
- 실체 클래스들의 공통된 필드와 메소드의 이름을 통일할 목적
→ 실체 클래스를 설계하는 사람이 여러 사람일 경우, 실체 클래스마다 필드와 메소드가 제각기 다른 이름을 가질 수 있다. - 실체 클래스를 작성할 때 시간 절약
선언
public abstract class 클래스{
int speed = 0;
public run(){
getSpeed()
System.out.println("달립니다.")
}
public void setSpeed()
}
추상 메소드와 오버라이딩
추상 클래스는 실체 클래스가 공통적으로 가져야 할 필드와 메소드들을 정의해 놓은 추상적인 클래스이므로 실체 클래스의 멤버를 통일화하는데 목적이 있다.
추상 클래스는 추상 메소드를 선언할 수 있다.
메소드의 선언부만 있고 메소드 실행 내용인 중괄호가 없는 메소드를 말한다.
추상 클래스를 설계할 때, 하위 클래스가 반드시 실행 내용을 채우도록 강요하고 싶은 메소드가 있을 경우 , 해당 메소드를 추상 메소드로 선언하면 된다.
public | protected abstract 리턴타입 메소드명();
public abstract class Animal{
public abstract void sound();
}
'책 > 이것이 자바다' 카테고리의 다른 글
[11장]기본 API클래스 (0) | 2022.02.14 |
---|---|
[10장]예외처리 (0) | 2022.02.14 |
[9장]중첩 클래스와 중첩 인터페이스 (0) | 2022.02.14 |
[8장]인터페이스 (0) | 2022.02.14 |
[6장] 객체 (0) | 2022.02.14 |