컴퓨터/JAVA

[Java] 자바의 상속(extends/super/overriding) 정리

도도새 도 2023. 6. 19. 01:35

자바의 상속

 

extends 키워드

 

extends 키워드를 사용하여 상속 관계를 구현할 수 있다.

상속은 코드의 재사용성과 확장성을 향상시킨다. 슈퍼 클래스에 공통된 특징과 동작을 정의하고, 이를 서브 클래스에서 상속받아 필요한 변경이나 추가를 할 수 있다. 이로써 코드 중복을 줄이고 유지보수성을 개선할 수 있다.

자식 클래스는 부모 클래스의 public혹은 protected혹은 default인 메소드나 멤버를 사용할 수 있다.

*자바에서는 기본적으로 모든 클래스는 extends Object즉, Obejct 클래스를 상속받는다.

 

public : 어디서든 접근 가능

protected : 서브 클래스에서 접근 가능

private : 상속되지 않으며 슈퍼 클래스 내부에서만 접근 가능

class ChildClass extends ParentClass {
  // 자식 클래스의 멤버 정의
}

 

super 키워드

 

자식 클래스의 생성자는 super()를 사용할 수 있다. super()란 부모 클래스의 생성자를 의미한다.

super()를 명시하지 않아도 자식 생성자는 부모 생성자를 자동으로 호출하게 된다. 즉, 자식 생성자는 우선 부모 생성자를 호출하게 된다.

 

또한 자식 클래스 내에서 super를 사용하여 부모 클래스의 멤버에 접근 가능하다.

private한 멤버는 super.로 접근할 수 없다.

super.맴버이름

 

 

overriding

 

자식 클래스에서는 부모 클래스에서 물려준 매소드 명을 동일하게 사용 가능하다.

다형성의 핵심 개념 중 하나로, 부모 클래스와 자식 클래스 간에 매서드 재정의를 통해 다양한 객체 동작을 표현 할 수 있다.

 

@Override 어노테이션을 사용해 명시적으로 오버라이딩 되었다는 것을 표현할 수 있다.

 

접근 제어자

  • 자식 클래스에서 오버라이딩되는 매서드의 접근 제어자는 부모 클래스의 머스더보다 더 제한적이거나 같아야한다.
  • 즉 부모 메서드가 public이면 자식 메서드는 public 으로 오버라이딩 가능하다.
  • 부모 메서드가 private면 오버라이딩 할 수 없다.
public class Animal {
    protected boolean isAnimal = true;
    Animal(){
        System.out.println("애니멀의 생성자");
    }

    void sound(){
        System.out.println("동물이 포효합니다.");
    }
    boolean isAnimal(){
        System.out.println("동물입니다.");
        return isAnimal;
    }
}

 

public class Cat extends Animal{
    @Override
    public void sound(){//오버라이딩
        System.out.println("고양이가 야옹 웁니다.");
    }
}

 

public class Dog extends Animal{

    @Override
    public void sound(){// 오버라이딩
        System.out.println("개가 멍멍 짖습니다.");
    }
}

 

public class Main {
    public static void main(String[] args){
        Dog dogy = new Dog();
        Cat navi = new Cat();

        dogy.sound();
        dogy.isAnimal();

        navi.sound();
        navi.isAnimal();

        Animal ani = (Animal)navi;
        ani.sound();
    }
}

 

출력값

애니멀의 생성자
애니멀의 생성자
개가 멍멍 짖습니다.
동물입니다.
고양이가 야옹 웁니다.
동물입니다.
고양이가 야옹 웁니다. // 실제 인스턴스 객체는 navi이므로 navi의 sound()가 호출

 

final 키워드

 

 

final 키워드가 붙은 클래스는 상속되지 않는다.

final 키워드가 붙은 메서드는 오버라이드 되지 않는다.

 

실습: 타자와 투수

 

부모 - 야구선수 : 번호, 이름, 키

자식 - 투수 : 승패 방어율

자식 - 타자 : 타수, 히트수, 타율

 

입력 -

1 or 2 (1은 투수, 2는 타자)

각 투수 혹은 타자의 정보

— 5번 반복

출력 - 각 투수 혹은 타자의 모든 정보

 

package pack1;

public class Player {
    protected int number;
    protected String name;
    protected int height;
    public Player(int number, String name, int height){
        this.number = number;
        this.name = name;
        this.height = height;
    }
    public void getPlayerInfo(){
        System.out.printf("number: %d\nname: %s\nheight: %d\n", this.number, this.name, this.height);
    }
}

 

package pack1;

public class Pitcher extends Player{
    private int win;
    private int lose;
    private double era;
    public Pitcher(int number, String name, int height, int win, int lose){
        super(number, name, height);
        this.win = win;
        this.lose = lose;
        this.era = (double)win/(double)(win+lose);
    }
    public void getPitcherInfo(){
        super.getPlayerInfo();
        System.out.printf("win : %d\nlose : %d\nERA: %f\n\n", this.win, this.lose, this.era);
    }
}

 

package pack1;

public class Hitter extends Player{
    private int ab;
    private int hit;
    private double ba;
    public Hitter(int number, String name, int height, int ab, int hit){
        super(number, name, height);
        this.ab = ab;
        this.hit = hit;
        this.ba = (double)hit/(double)ab;
    }
    public void getHitterInfo(){
        super.getPlayerInfo();
        System.out.printf("ab: %d\nhit: %d\nba: %f\n\n", this.ab, this.hit, this.ba);
    }
}

 

package pack1;

import java.util.Scanner;

public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);

        Player players[] = new Player[5];

        for(int i = 0; i < 5; i++){
            System.out.println("투수 (1) 타자 (2)");
            int temp = sc.nextInt();
            if(temp == 1){
                System.out.println("번호, 이름, 키, win, lose 입력");
                int num = sc.nextInt();
                String name = sc.next();
                int height = sc.nextInt();
                int win = sc.nextInt();
                int lose = sc.nextInt();
                players[i] = new Pitcher(num, name, height, win, lose);
            }
            if(temp == 2){
                System.out.println("번호, 이름, 키, ab, hit 입력");
                int num = sc.nextInt();
                String name = sc.next();
                int height = sc.nextInt();
                int ab = sc.nextInt();
                int hit = sc.nextInt();
                players[i] = new Hitter(num, name, height, ab, hit);
            }
        }

        for(Player player:players){
            if(player instanceof Pitcher){
                ((Pitcher) player).getPitcherInfo();
            }
            else if(player instanceof Hitter){
                ((Hitter) player).getHitterInfo();
            }
        }
    }
}

 

 

입력값

투수 (1) 타자 (2)
1
번호, 이름, 키, win, lose 입력
11 mimi 170 20 30
투수 (1) 타자 (2)
1
번호, 이름, 키, win, lose 입력
10 minji 150 5 6
투수 (1) 타자 (2)
2
번호, 이름, 키, ab, hit 입력
8 gugucon 185 12 30
투수 (1) 타자 (2)
2
번호, 이름, 키, ab, hit 입력
1 gimi 175 30 12
투수 (1) 타자 (2)
2
번호, 이름, 키, ab, hit 입력
5 mingu 178 45 20

 

출력값

number: 11
name: mimi
height: 170
win : 20
lose : 30
ERA: 0.400000

number: 10
name: minji
height: 150
win : 5
lose : 6
ERA: 0.454545

number: 8
name: gugucon
height: 185
ab: 12
hit: 30
ba: 2.500000

number: 1
name: gimi
height: 175
ab: 30
hit: 12
ba: 0.400000

number: 5
name: mingu
height: 178
ab: 45
hit: 20
ba: 0.444444