[Java] 상속, 오버라이딩, 오버로딩, 다형성

킹발·2022년 9월 26일
0

Java

목록 보기
5/12
post-thumbnail

상속

상속에 대한 이해

상속이란?

  • 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것
  • 상속해주는 클래스를 부모 클래스 라 하고 상속 받는 클래스를 자손 클래스 라 한다.

상속을 구현하는 법

새로 작성하고자 하는 클래스의 이름 뒤에 상속받고자 하는 클래스의 키름을 키워드 extends 와 함께 써 주기만 하면 된다.

class Parent {
	int age;
}

class Child extends Parent{ }

상속 특징

  • 자손 클래스는 조상 클래스의 모든 멤버를 상속받는다. (단, 생성자의 초기화 블럭은 상속되지 않는다.)
  • 자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다.

상속을 사용 하는 이유

  • 상속을 사용하면 중복되는 코드를 줄일 수 있다.
  • 상속받아서 이미 존재하는 클래스의 필드와 메서드를 재사용할 수 있다.
  • 공통되는 부분을 부모로 빼서 상속을 사용하면 위와 같은 이점을 가져올 수 있다.

상속에서의 생성자

  • 생성자는 상속이 되지 않는다.
  • 자식 클래스로 인스턴스를 생성할 때 부모 클래스의 기본 생성자를 자동으로 호출한다.
class GrandParent {
    public GrandParent() {
        System.out.println("GrandParent 생성자 호출");
    }
}
class Parent extends GrandParent {
    public Parent() {
    	//super(); 생략
        System.out.println("Parent 생성자 호출");
    }
}
class Child extends Parent {
    public Child() {
    	//super(); 생략
        System.out.println("Child 생성자 호출");
    }
}

public class extendsConstructor {
    public static void main(String[] args) {
       Child child = new Child();
    }
}
GrandParent 생성자 호출
Parent 생성자 호출
Child 생성자 호출

why?

  • 자식 클래스 객체 안에는 부모 클래스에서 상속된 부분이 들어 있다.

    부모로부터 물려받은 변수는 자식 클래스에서 초기화하는게 아니라 부모 클래스의 생성자를 통해 초기화 하는게 바람직하다.

super()

참조변수 super

  • 상속받은 멤버와 자신의 멤버와 이름이 같을 때는 super 를 붙여서 구별
class Parent1 {
    int x = 10;
}

class Child1 extends Parent1{
    int x = 20;

    void method() {
        System.out.println("x = " + x);
        System.out.println("this.x = " + this.x);
        System.out.println("super.x = " + super.x);
    }
}

public class superVar {
    public static void main(String[] args) {
        Child1 child1 = new Child1();
        child1.method();
    }
}
x = 20
this.x = 20
super.x = 10

조상의 생성자 - super()

  • super() 는 부모의 생성자를 호출하는데 사용
  • 클래스 자신에 선언된 변수는 자신의 생성자가 초기화를 책임지도록 작성하는 것이 좋다
class Tv{
    private int size;

    public Tv(int size) {
        this.size = size;
    }

    public int getSize() {
        return size;
    }
}

class ColorTv extends Tv {
    private int resolution;

    public ColorTv(int size, int resolution) {
        super(size);
        this.resolution = resolution;
    }

    public int getResolution() {
        return resolution;
    }
}
public class Ex1 {
    public static void main(String[] args) {
        ColorTv myTv = new ColorTv(32, 1024);
        System.out.println(myTv.getSize() + "인치 " + myTv.getResolution() + "컬러");
    }
}
32인치 1024컬러

상속 예제

1번

class Tv{
    private int size;

    public Tv() {

    }
    public Tv(int size) {
        this.size = size;
    }

    protected int getSize() {
        return size;
    }
}

class ColorTv extends Tv {
    private int color;

    public ColorTv(int size, int color) {
        super(size);
        this.color = color;
    }

    public void printProperty() {
        System.out.println(super.getSize() + "인치 " + color + "컬러");
    }
}
public class Ex1 {
    public static void main(String[] args) {
        ColorTv myTv = new ColorTv(32, 1024);
        myTv.printProperty();
    }
}

2번

class Tv{
    private int size;

    public Tv(int size) {
        this.size = size;
    }

    public int getSize() {
        return size;
    }
}

class ColorTv extends Tv {
    private int resolution;

    public ColorTv(int size, int resolution) {
        super(size);
        this.resolution = resolution;
    }

    public int getResolution() {
        return resolution;
    }
}

class IpTv extends ColorTv {
    private String ip;

    public IpTv(String ip, int size, int resolution) {
        super(size, resolution);
        this.ip = ip;
    }

    void printProperty() {
        System.out.println("나의 IpTv는 " + ip + " 주소의 " + 
                super.getSize() + "인치 " + super.getResolution() + "컬러");
    }
}
public class Ex1 {
    public static void main(String[] args) {
        IpTv ipTv = new IpTv("192.1.1.2", 32, 2048);
        ipTv.printProperty();
    }
}



overriding

  • 상속받은 메서드의 내용을 변경 하는 것

오버라이딩 조건

  1. 접근 제어자는 부모 클래스의 메서드보다 좁은 범위로 변경 할 수 없다.
  2. 부모 클래스의 메서드보다 많은 수의 예외를 선언할 수 없다.
  3. 선언부가 부모 클래스의 메서드와 일치해야 한다.
class Parent2{
    void parentMethod() throws IOException, SQLException {
        System.out.println("Parent2");
    }
}

class Child2 extends Parent2 {
    @Override
    // 부모보다 예외 더 많이 선언하거나 범위가 더 좁은 접근 제어자 private 을 쓰면 ERROR
    void parentMethod() throws IOException { 
        System.out.println("Child2");
    }
}

public class overridingEx {
    public static void main(String[] args) throws IOException {
        Child2 child2 = new Child2();
        child2.parentMethod();
    }
}

overloading

  • 기존에 없는 새로운 메서드를 정의하는 것
  • println오버로딩의 대표적 예시

오버로딩 조건

  1. 메서드 이름이 같아야 한다.
  2. 매개변수의 개수 or 타입이 달라야 한다.
  3. return 타입은 영향이 없다.
class Parent{
    void parentMethod() {
        System.out.println("Hello");
    }
}

class Child extends Parent {
    void parentMethod(String name) {
        System.out.println("Hello " + name);
    }
}

public class overloadingEx {
    public static void main(String[] args) {
       Child child = new Child();
       child.parentMethod();
       child.parentMethod("JaeHyun");
    }
}
Hello
Hello JaeHyun

다형성

다형성의 이해

다형성 이란?

  • 부모 타입 참조 변수로 자손 타입 객체를 다루는 것
Parent p = new Child(); // Ok
Child c = new Parent(); // Error
class Phone {
    String phoneNum;
    
    void sendMessage() {
        System.out.println("메시지 전송");
    }
}

class SmartPhone extends Phone {
    void sendKakao() {
        System.out.println("카카오톡 전송");
    }
}
public class polyEx {
    public static void main(String[] args) {
        Phone phone = new SmartPhone();
        Phone.sendMessage();
    }
}

자식으로 부모 인스턴스 호출 가능?

  • 메모리에 올라가는 것
    • String phoneNum
    • sendMessage()
  • 자식 참조변수로 호출할 수 있는 것
    • String phoneNum
    • sendMessage()
    • sendKakao()

실제 메모리에 올라가는 것 보다 자식 참조 변수로 호출할 수 있는 것이 많기 때문에 Error

instanceof 연산자

  • 참조변수의 타입과 실제 가리키는 인스턴스의 타입이 항상 같지 않으므로 형변환이 가능한지 불가능한지 확인할 수 있는 연산자
  • 연산의 결과로 true or false
  • 연산결과가 true 라면 참조변수가 검사한 타입으로 형변환이 가능하다는 것
class Car {
    void run() {
        System.out.println("run");
    }
}

class FireEngine extends Car {
    void water() {
        System.out.println("water");
    }
}

class Ambulance extends Car {
    void medic() {
        System.out.println("medic");
    }
}

public class Instanceof {
    public static void main(String[] args) {
        Car car = new Ambulance();
        
        if (car instanceof Ambulance) {
            Ambulance am = (Ambulance) car;
            am.medic();
        }
    }
}

다형성 활용

여러 종류의 객체를 배열로 다루기

class Car {
    void run() {
        System.out.println("run");
    }
}

class FireEngine extends Car {
    void water() {
        System.out.println("water");
    }
}

class Ambulance extends Car {
    void medic() {
        System.out.println("medic");
    }
}

public class Instanceof {
    public static void main(String[] args) {
        Car[] cars = new Car[2];
        cars[0] = new FireEngine();
        cars[1] = new Ambulance();

        for (Car car : cars) {
            if (car instanceof Ambulance) {
                Ambulance am = (Ambulance) car;
                am.medic();
            }
            else if (car instanceof FireEngine) {
                FireEngine fe = (FireEngine) car;
                fe.water();
            }
        }
    }
}

0개의 댓글