Practice JAVA - 상속, 추상 클래스

최정환·2022년 12월 14일
0

Practice JAVA

목록 보기
7/10

상속(super, override)

이미 존재하는 클래스를 재사용해서 새로운 클래스를 만들 수 있어 중복 코드를 줄여준다.
부모 클래스에서 수정이 일어나면 자식들에게도 일어나기 때문에 유지보수가 쉬우면서도 어렵다.

클래스 상속

코드에서 클래스를 상속받는 방법

class 자식 extends 부모 {}

상속을 할 때 주의해야할 특징이 있다.

  • 부모는 여러 개가 있을 수 없다.
  • 부모에서 private를 가지고 있는 필드, 메소드를 상속에서 제외된다.

기본 생성자가 있는 클래스 상속

class Human {
    String name;
    int age;
    String job;
    private int iq;
    protected String hair;
}

class Me extends Human {
    // Human을 상속 받았기 때문에 Human이 this가 된다. = Human의 필드를 가지고 있다.
    // private인 iq는 상속 받지 못하고 protected와 defualt 는 받을 수 있다.
    Me(String name, int age, String job, String hair){
        this.name = name;
        this.age = age;
        this.job = job;
        this.hair = hair;
    }
}

기본 생성자가 없는 클래스 상속

class Human2 {
    String name;
    int age;

    Human2(String name, int age){
        this.name = name;
        this.age = age;
    }
}


class Me2 extends Human2{
    Me2(String name, int age) {
        super(name, age);
    }
}

메소드 재정의

상속 받은 클래스에 있는 메소드를 다르게 사용하고 싶다면 재정의를 할 수 있다.

pulbic class Human {
	void sayHi(String name){
    	System.out.println(name);
    }
}


public class Me extends Human{
	@Override
    void sayHi(String name){
    	System.out.println(name+"안녕");
    }
}

재정의 규칙

  • 부모의 메소드와 동일한 시그니처(리턴 타입, 메소드 이름, 매개 변수 목록)를 가져야한다.
  • 접근 제한 더 강하게 재정의 불가
  • 새로운 예외를 throws할 수 없다.

상속에서 final

final 클래스는 상속 불가

클래스를 선언할 때 final 키워드를 주면 해당 클래스는 최종적인 클래스가 되어 상속을 할 수 없다.

재정의 할 수 없는 메소드

final은 최종이기 때문에 메소드를 재정의 할 수 없다.



타입 변환

다형성

다양한 객체를 이용해서 다양한 실행결과가 나오도록 하는 성질

예를 들면 자동차가 타이어를 사용하는 방법은 동일하지만 어떤 타이어를 사용하느냐에 따라 성능이 달라질 수 있다.

자동 타입 변환

자동 타입 변환은 프로그램 실행 도중에 자동적으로 타입 변환이 일어나는 것을 말한다.

자동 타입 변환의 개념은 자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급될 수 있다는 것이다.

부모타입 변수 = 자식타입

// Cat은 Animal을 상속받은 클래스라 가정한다.
// 자식타입은 부모타입으로 자동 타입 변환이 일어날 수 있다.
// animal, cat은 동일한 Cat의 메모리 주소를 참조한다.
Cat cat = new Cat();
Animal animal = cat;

cat == animal // true

강제 타입 변환

부모 타입을 자식 타입으로 변환하는 것

모든 부모 타입을 자식 타입으로 강제 변환이 가능한 것은 아니다.
자식 타입이 부모 타입으로 자동 타입 변환한 후 다시 자식 타입으로 변환할 때 강제 타입 변환을 사용할 수 있다.

Parent parent = new Child();
Child child = (Child) parent;

추상 클래스

객체를 직접 생성할 수 있는 실체 클래스와 달리 공통적인 특성을 추출해 선언한 클래스를 추상 클래스라고 한다.

추상 클래스가 부모, 실체 클래스가 자식으로 구현되어 실체 클래스는 추상 클래스의 모든 특성을 물려받고 추가적인 특성을 가질 수 있다.

특성 : 필드, 메소드

용도

공통된 필드와 메소드의 이름을 통일할 목적

실체 클래스를 설계하는 사람이 여러 사람일 경우 실체 클래스마다 필드와 메소드가 제각기 다른 이름을 가질 수 있다.

예를 들면 소유자의 이름을 저장하는 필드를 Galaxy 클래스에서 owner고 Apple 클래스에선 user라고 한다. 그리고 전원을 키는 메소드는 Galaxy는 PowerOn, Apple은 TurnOn이다.

이렇게 같은 기능을 하는데 필드의 이름이 다르다면 객체마다 사용 방법이 달라진다.
추상 클래스는 필드와 메소드를 선언하고 두 클래스에 상속함으로서 필드와 메소드 이름을 통일할 수 있어 이러한 점을 해결하는데 도움이 된다.

실체 클래스를 작성할 시간 절약

공통적인 필드와 메소드는 추상 클래스인 Phone에 모두 선언해두고 다른 점만 실체 클래스에 선언하면 실체 클래스를 작성하는데 시간을 절약할 수 있다.

선언

abstract 키워드를 선언해 준다.

public abstract class Phone{}

추상 클래스

abstract class Phone{
    public String owner;
    public Phone(String owner){
        this.owner = owner;
    }
    
    public void turnOn(){
        System.out.println("Phone on");
    }
    public void turnOff(){
        System.out.println("Phone off");
    }
}

class Galaxy extends Phone {
    public Galaxy(String owner){
        super(owner);
    }
    
    public void search(){
        System.out.println("전화번호 찾기");
    }
}

추상 클래스는 실체 클래스의 공통되는 필드, 메소드를 추출해서 만들었기 때문에 객체를 직접 생성해 사용이 불가하다.

추상 메소드, 재정의

메소드 선언만 통일하고 실행 내용은 실체 클래스마다 달라야 하는 경우가 있다.

이런 경우를 위해 추상 클래스는 추상 메소드를 선언할 수 있다.

// 추상 메소드는 함수 내용을 가질수 없다.
public abstract void ring();
abstract class Phone{
    public String owner;
    public Phone(String owner){
        this.owner = owner;
    }

    public void turnOn(){
        System.out.println("Phone on");
    }
    public void turnOff(){
        System.out.println("Phone off");
    }
    // abstract 메소드는 본문을 가질수 없다.
    public abstract void ring();
}

class Galaxy extends Phone {
    public Galaxy(String owner){
        super(owner);
    }

    public void search(){
        System.out.println("전화번호 찾기");
    }

    @Override
    public void ring() {
        System.out.println("GalGal");
    }
}
class Apple extends Phone {
    public Apple(String owner){
        super(owner);
    }

    @Override
    public void ring() {
        System.out.println("AppApp");
    }
}

0개의 댓글