7.4 매서드 재정의 (다형성 관련)

부모 클래스의 메소드가 자식 클래스가 사용하기에 적합하지 않을 경우,

자식 클래스에서 재정의해서 사용메소드 오버라이딩(Overriding)

 

● 부모 메소드의 선언부(리턴 타입, 메소드 이름, 매개변수)와 동일해야 함.

●접근 제한을 더 강하게 오버라이딩할 수 없다.(public → private 변경 불가)

●새로운 예외를 throws할 수 없다.

 

public class Calculator {
	public double areaCircle(double r) {
    	return 3.14159 * r * r;
	}
}

public class Computer extends Calculator { 	// Calculator 클래스를 상속받음
	@Override
    public double areaCircle(double r) {
    	return Math.PI * r * r;		// 리턴 값을 재정의
	}
}

@Override를 붙이면 컴파일 단계에서 정확히 오버라이딩 되었는지 체크하고, 문제가 있다면 컴파일 에러를 출력.

(Ctrl + Spacebar)로 편하게 이용할 수 있다.

 

★ 메소드 재정의할 때

부모 메소드의 일부만 변경된다 해도 중복된 내용을 자식 메소드가 가지고 있어야 함.

public class Parent {
	pulbic void method() {
    	...
        ...
        ...
	}
}

public class Child extends Parent {	// 상속받는 클래스
	pulbic void method() {
    	super.method();
        // 추가할 작업처리
        ...
	}
}

자식 메소드와 부모 메소드의 공동 작업 처리 기법을 이용하여 매우 간단하게 해결 가능

super.부모메소드; 로 숨겨진 부모 메소드를 호출할 수 있다. (위치 상관없음)

 

 

7.5 final 클래스와 final 메소드

● class 앞에 final을 붙이게 되면 최종적인 클래스가 되므로 더 이상 상속할 수 없는 클래스가 된다.

ex) public final class 클래스이름 { ... }

 

● 메소드를 선언시 final을 붙이면 최종적인 메소드가 되므로 오버라이딩할 수 없는 메소드가 된다.

ex) public final void stop() { ... }

 

 

7.6 protected 접근 제한자

※ 접근 제한이 강화되는 순서

public < protected < default < private

접근 제한자 제한 대상 제한 범위
protected 필드, 생성자, 메소드 같은 패키지이거나, 자식 객체만 사용 가능

즉, 다른 패키지여도 자식 객체라면 사용 가능 (default는 같은 패키지만 가능)

 

 

7.7 타입 변환

2장에서 배운 '기본 타입 변환'과 비슷한 개념. '참조 타입 변환'이라고 보면 된다.

클래스도 마찬가지로 타입 변환이 있다.

 

● 자동 타입 변환

자식은 부모의 특정 기능을 상속받기 때문에 부모와 동일하게 취급될 수 있다.

class Animal { ... } 	// 상위
class Cat extends Animal { ... } 	// 하위

예를 들어 '고양이는 동물이다'가 성립한다는 것이다.

Cat cat = new Cat();
Animal animal = cat;

cat과 animal 변수는 타입만 다를 뿐, 동일한 Cat 객체를 참조한다.

cf) 자식 객체를 생성할 시, 부모 객체도 생성된다.

 

또한 바로 위의 부모가 아니더라도 상속 계층에서 상위 타입이라면 자동 타입 변환이 일어날 수 있다.

public class A { ... }
public class B extends A { ... }
public class C extends B { ... }  // 이 경우, C는 A의 상속 관계에 있다

C c = new C();
A a = c;	// 자동 타입 변환 된다

 

 

● 강제 타입 변환

반대로 부모 타입은 자식 타입으로 자동 변환되지 않는다.

이러한 경우 강제 타입 변환(Casting)을 해주어야 한다.

 

부모 타입 객체를 자식 타입으로 무조건 강제 변환할 수 있는 것은 아니다.

자식 객체가 부모 타입으로 자동 변환 된 후 다시 자식 타입으로 변환할 때 강제 타입 변환을 사용할 수 있다.

Parent parent = new Child();  // 자동 타입 변환
Child child = (Child) parent;  // 강제 타입 변환

 

 

7.8 다형성 (중요)

사용 방법은 동일하지만 실행 결과가 다양하게 나오는 성질

→ 프로그램을 구성하는 객체를 바꾸면 프로그램의 실행 성능이 다르게 나올 수 있음을 의미

 

객체 사용 방법이 동일하다? → 동일한 메소드를 가지고 있다는 뜻

 

예시) 필드의 다형성

public class Tire {
	public void roll() {
    	System.out.println("회전합니다.");
    }
}

public class HankookTire extends Tire {
	@Override
	public void roll() {
    	System.out.println("한국 타이어가 회전합니다.");
    }
}

public class KumhoTire extends Tire {
	@Override
	public void roll() {
    	System.out.println("금호 타이어가 회전합니다.");
    }
}

위의 코드처럼 큰 개념의 Tire가 있고 그 아래에  한국Tire금호Tire가 있는데, 쓰임새는 동일하다.

하지만 종류에 따른 타이어는 성능을 달리한다.

public class Car {
	public Tire tire;
    
    public void run() {
    	tire.roll();
    }
}

자동차의 설계도 안에는 Tire부품이 있다. 그리고 run()이라는 동작을 한다.

여기서 run() 동작은 Tire가 무엇이냐에 따라 성능을 달리할 수 있다는 것이다.

// main 메소드 안
Car myCar = new Car();  // Car 설계도를 따른 변수 myCar 변수 선언

myCar.tire = new Tire();  // myCar의 타이어를 일반적인 Tire 객체로 구성

myCar.tire = new HankookTire();  // myCar의 타이어를 한국Tire 객체로 구성

myCar.tire = new KumhoTire();  // myCar의 타이어를 금호Tire 객체로 구성

 

 

다형성은 필드보다 메소드를 호출할 때 많이 발생

메소드가 클래스 타입의 매개변수를 가지고 있을 경우,

호출할 때 동일한 타입의 객체를 제공하는 것이 정석이지만

자식 객체를 제공할 수도 있다. → 여기서 다형성이 발생

public class Vehicle {
	public void run() {
    	system.out.println("차량이 달립니다.");
    }
}

public class Bus extends Vehicle {
	@Override
    public void run() {
    	system.out.println("버스가 달립니다.");
    }
}

public class Taxi extends Vehicle {
	@Override
    public void run() {
    	system.out.println("택시가 달립니다.");
    }
}

public class Driver {
	public void drive(Vehicle vehicle){
    	vehicle.run();
    }
}

Vehicle을 상속 받는 Bus와 Taxi가 있고, 이러한 이동수단을 이용하는 Driver가 있다고 해보자.

Driver의 동작은 이러한 이동수단들을 drive 메소드로 받을 수 있다.

// main 메소드 안
Driver driver = new Driver();  // 운전자 객체 생성

Bus bus = new Bus();  // 버스 객체 생성
driver.drive(bus);  // 운전자는 Vehicle의 자식 객체 Bus를 운전함. // 자동 타입 변환

Taxi taxi = new Taxi();  // 택시 객체 생성
driver.drive(taxi);  //  운전자는 Vehicle의 자식 객체 Taxi를 운전함. // 자동 타입 변환

 

 

7.9 객체 타입 확인

매개변수의 다형성에서 실제로 어떤 객체가 매개값으로 제공되었는지 확인하는 방법

boolean result = 객체 instanceof 객체의타입;

 

예를 들어보자.

public void method(Parent parent) {
	if(parent instanceof Child) {
    	Child child = (Child) parent;
    }
}

Child 타입으로 강제 타입 변환하기 전에 매개값이 Child 타입인지 여부를 instanceof 연산자로 확인.

Child 타입이 아니라면 강제 타입 변환을 할 수 없기 때문

강제 타입 변환을 하는 이유? Child 객체의 모든 멤버(필드, 메소드 등)에 접근하기 위해서

 

JAVA 12부터 instanceof 연산의 결과가 true일 경우, 우측 타입 변수를 사용할 수 있기 때문에 강제 타입 변환이 필요 없다.

if(parent instanceof Child child) {
	// 강제 타입 변환 필요 없이 바로 child 변수 사용 가능
}

 

 

7.10 추상 클래스

객체를 생성할 수 있는 클래스를 실체 클래스라고 한다면,

이 클래스들의 공통적인 필드나 메소드를 추출해서 선언한 클래스 (실체 클래스의 부모 역할)

객체를 직접 만들지 못하고 상속을 통해 자식 클래스만 만들 수 있다.

public abstract class 클래스명 {
    // 필드
    // 생성자
    // 메소드
}

위 처럼 클래스 선언에 abstract 키워드를 붙이면 추상 클래스 선언이 된다.

자식 객체가 생성될 때 super()로 추상 클래스의 생성자가 호출되기 때문에

생성자도 반드시 있어야 한다.

 

예시)

public abstract class Phone {
	// Field 선언
    String owner;
    
    // Constructor 선언
    Phone(String owner) {
    	this.owner = owner;
    }
    
    // Method 선언
    void turnOn() {
    	System.out.println("폰 전원을 켭니다.");
    }
    void turnOff() {
    	System.out.println("폰 전원을 끕니다.");
    }
}

public class SmartPhone extends Phone {
    // Constructor 선언
    SmartPhone(String owner) {
    	// Phone Constructor 호출
        super(owner);
    }
    
    // Method 선언
    void internetSearch() {
    	System.out.println("인터넷 검색을 합니다.");
    }
}

// main 메소드 안
SmartPhone smartPhone = new SmartPhone("홍길동");

smartPhone.turnOn();  // Phone 클래스 안의 메소드 사용
smartPhone.internetSearch();  // SmartPhone 클래스 안의 메소드 사용
smartPhone.turnOff();  // Phone 클래스 안의 메소드 사용

 

 

● 추상 메소드와 재정의

자식 클래스들이 가지고 있는 공통 메소드를 뽑아 추상 클래스로 작성할 때,

메소드 선언부(리턴타입, 메소드명, 매개변수)만 동일.

실행 내용은 자식 클래스마다 달라야 하는 경우가 많음.

public abstract class Animal {
	// 추상 메소드 선언
    abstract void sound();
}

추상 메소드는 자식 클래스의 공통 메소드라는 것만 정의.

실행 내용은 가지지 않는다.

→ 자식 클래스에서 반드시 재정의(오버라이딩)해서 실행 내용을 채워야 함.

'JAVA' 카테고리의 다른 글

15일차 2024 - 3 - 18  (0) 2024.03.18
11일차 2024 - 3 - 12  (0) 2024.03.17
14일차 2024 - 3 - 15  (0) 2024.03.14
13일차 2024 - 3 - 14  (0) 2024.03.14
12일차 2024 - 3 - 13  (0) 2024.03.13

+ Recent posts