컴퓨터 프로그래밍/Java

[Java] 상속

한33 2024. 7. 29. 18:02

상속

상속을 사용하면 코드의 중복이 제거되고 재사용성이 크게 증가하여 생산성과 유지 보수성에 매우 유리해짐

public class 자식클래스 extends 부모클래스 {

}

※ 주의

상속은 확장의 개념. 부모 클래스의 멤버의 개수는 자식 클래스의 멤버의 수보다 클 수가 없다.


클래스 간의 관계

상속관계 : is -a ( 스포츠카는 자동차다 )

포함관계 : has -a ( 자동차가 4개의 타이어, 4개의 문을 가지고 있음 )

 

Main.java

// 자동차 객체 생성
Car car = new Car("GV80", "Black", 50000000);

// 자동차 부품 : 타이어, 차문, 핸들 선언
Tire[] tires = new Tire[]{
        new Tire("KIA", 150000), new Tire("금호", 150000),
        new Tire("Samsung", 150000), new Tire("LG", 150000)
};
Door[] doors = new Door[]{
        new Door("LG", "FL"), new Door("KIA", "FR"),
        new Door("Samsung", "BL"), new Door("LG", "BR")
};
Handle handle = new Handle("Samsung", "S");


// 자동차 객체에 부품 등록
car.setTire(tires);
car.setDoor(doors);
car.setHandle(handle);

 

Car.java

Tire[] tire;
Door[] door;
Handle handle;

public Car(String model, String color, double price) {
    this.model = model;
    this.color = color;
    this.price = price;
}

public void setTire(Tire ... tire) {
    this.tire = tire;
}

 

 

Car.java 에는 Tire, Door, Handle 클래스가 포함되어있고 Main.java 에서는 Car , Tire, Door, Handle 객체가 생성된 후에

자동차 객체에 부품등록을 하여서 포함시키고 있다.

 

Car.java 에서는 이미 해당 클래스가 포함되어 선언이 되어있고, setTire() 메서드 매개변수로 ... 을 받아 여러 개의 매개변수를 받을 준비까지 되어있다.


단일 상속과 다중 상속

Java 는 다중 상속을 허용하지 않음.

여러 부모 클래스가 한 자식클래스에 상속할 수 없다. ( 멤버 이름이 겹친다든지 문제가 발생 )

 

final 클래스와 final 메서드

final 키워드를 클래스에 지정하여 선언하면 최종적인 클래스가 됨으로 더 이상 상속할 수 없는 클래스가 됨

final 키워드를 메서드에 지정하여 선언하면 최종적인 메서드가 됨으로 더 이상 오버라이딩할 수 없는 메서드가 됨


Object

Object 클래스는 Java 내 모든 클래스들의 최상위 부모 클래스 → 모든 클래스는 Object 메서드를 사용할 수 있음

부모 클래스가 없는 자식 클래스는 컴파일러에 의해 자동으로 Object 클래스를 상속받게 됨.


오버라이딩

부모 클래스로부터 상속받은 메서드의 내용을 재정의 하는 것

 

조건

  1. 선언부가 부모 클래스의 메서드와 일치해야 합니다.
  2. 접근 제어자를 부모 클래스의 메서드 보다 좁은 범위로 변경할 수 없습니다.
  3. 예외는 부모 클래스의 메서드 보다 많이 선언할 수 없습니다.
@Override
public double brakePedal() {
    speed = 100;
    System.out.println("스포츠카에 브레이크란 없다");
    return speed;
}

@Override
public void horn() {
    booster();
}

 

자식 클래스에서 @Overriding 을 적어주고 메서드를 재정의 해준다.

 

super 와 super()

super 은 부모 클래스의 멤버를 참조할 수 있는 키워드

public void setCarInfo(String model, String color, double price) {
    super.model = model; // model은 부모 필드에 set
    super.color = color; // color는 부모 필드에 set
    this.price = price; // price는 자식 필드에 set
}

 

자식 클래스에서 위처럼 메서드를 설정하면 super 을 붙인 model 과 color 은 부모 클래스에 접근해서 부모 클래스의 필드의 값을 수정한다.

 

price 는 this 를 사용했기 때문에 자식 클래스에 해당하는 price 필드를 수정한다.


다형성

자동 타입 변환

부모 타입 변수 = 자식 타입 객체; 는 자동으로 부모 타입으로 변환이 일어남.

→ 자식 객체는 부모 객체의 멤버를 상속받기 때문에 부모와 동일하게 취급될 수 있음

Mammal mammal = new Whale();

( Mammal 이 Whale 의 부모 타입 )

 

강제 타입 변환

반대로 부모 타입 객체는 자식 타입 변수로 자동으로 타입 변환되지 않음.

// 자식타입객체가 자동 타입변환된 부모타입의 변수
        Mammal mammal = new Whale();
        mammal.feeding();

// 자식객체 고래의 수영 기능을 사용하고 싶다면
// 다시 자식타입으로 강제 타입변환을 하면된다.
        Whale whale = (Whale) mammal;
        whale.swimming();

 

※ 주의

아무 때나 강제 타입 변환이 가능한 게 아니라, 자식 타입 객체가 부모 타입 변환된 후 다시 자식 타입으로 변환될 때만 강제 타입 벼환이 가능

 

다형성

여러 가지 형태를 가질 수 있는 능력

예를 들어 '자동차의 바퀴를 교체하면 승차감이 좋아진다' 와 같음

Tire tire = new HankookTire("HANKOOK");
Tire tire = new KiaTire("KIA");

 

Tire 의 자식 클래스 HankookTire 과 KiaTire 선언.

 

public Car(Tire tire) {
            this.tire = tire;
        }

...

        Car car1 = new Car(new KiaTire("KIA"));
        Car car2 = new Car(new HankookTire("HANKOOK"));

 

매개변수에도 다형성이 적용될 수 있음

Car 생성자에서 매개변수의 타입이 부모 타이어이기 때문에 자식 타이어 객체들을 매개값으로 전달할 수 있음

( 결국은 Car car1 =  new Car (tire) )  와 같은 셈

 

        Tire getHankookTire() {
            return new HankookTire("HANKOOK");
        }

        Tire getKiaTire() {
            return new KiaTire("KIA");
        }

...

        Tire hankookTire = car1.getHankookTire();
        KiaTire kiaTire = (KiaTire) car2.getKiaTire();

 

반환 타입이 부모타이어이기 때문에 자식 타이어 객체들을 반환값으로 지정할 수 있음.

 

마찬가지로 자동 타입 변환이 된 반환값인 자식 타이어 객체를 강제 타입 변환할 수도 있음 ( 조건이 성립 )


instanceof

다형성 기능으로 해당 클래스 객체의 원래 클래스명을 체크하는 것이 필요한데 instanceof 가 이 기능을 한다.

// 다형성

        class Parent { }
        class Child extends Parent { }
        class Brother extends Parent { }


        public class Main {
            public static void main(String[] args) {

                Parent pc = new Child();  // 다형성 허용 (자식 -> 부모)

                Parent p = new Parent();

                System.out.println(p instanceof Object); // true 출력
                System.out.println(p instanceof Parent); // true 출력
                System.out.println(p instanceof Child);  // false 출력

                Parent c = new Child();

                System.out.println(c instanceof Object); // true 출력
                System.out.println(c instanceof Parent); // true 출력
                System.out.println(c instanceof Child);  // true 출력

            }
        }

 

{대상 객체} instance of {클래스 이름} 와 같은 형태로 사용하면 응답값은 boolean 으로 결과를 출력해냄

 


추상 클래스

추상 클래스

미완성된 설계도

abstract 키워드를 사용하여 선언

public abstract class 추상클래스명 {

}

 

  • 추상 클래스는 추상 메서드를 포함할 수 있다. ( 추상 메서드가 없어도 추상 클래스로 선언 가능 )
  • 추상 클래스는 자식 클래스에 상속되어 자식 클래스에 의해서만 완성될 수 있음
  • 추상 클래스는 여러 개의 자식 클래스들에서 공통적인 필드나 메서드를 추출해서 만듦

추상 메서드

아직 구현되지 않은 미완성된 메서드

public abstract class 추상클래스명 {
    abstract 리턴타입 메서드이름(매개변수, ...);
}

 

추상 메서드는 일반적인 메서드와는 다르게 블록 {} 이 없음 ( 정의만 할 뿐, 실행 내용은 가지고 있지 않음 )

 

추상 클래스 상속

public class 클래스명 extends 추상클래스명 {
    @Override
    public 리턴타입 메서드이름(매개변수, ...) {
        // 실행문
    }
}

 

extends 를 통해 추상 클래스에 상속시키고 @Override 를 필수로 사용해 추상 메서드를 완성시킨다.

 

여러 개의 클래스에서 공통된 부분을 뽑아서 코드를 간단화하고 이를 묶어서 추상 클래스로 만들어서 뽑아쓰게 만든다고 이해하자.

 

'컴퓨터 프로그래밍 > Java' 카테고리의 다른 글

[Java] 예외처리  (0) 2024.07.30
[Java] 인터페이스  (0) 2024.07.30
[Java] this와 this(), 접근 제어자, package와 import  (0) 2024.07.29
[Java] 생성자  (0) 2024.07.28
[Java] 인스턴스 멤버와 클래스 멤버  (0) 2024.07.26