TIL. 상속, 추상, 인터페이스

hyuko·2023년 1월 10일
0

Java

목록 보기
20/26

상속

상속이란?

  • extends 영어의 의미를 해석하자면 확장의 개념이다.

    메모리 공간을 확장한다는 의미 자식 클래스에서 상속받을
    부모 클래스를 붙여 공간을 확장해서 만들겠다는 의미이다.

상속의 특징

  1. 자식클래스에서 부모클래스를 상속받게되면 자식클래스는
    부모클래스가 생성이 먼저 되고 자식 클래스가 생성된다.

  2. 상속은 부모 클래스는 자식 클래스를 여러개 둘 수 있다.

  3. 상속은 자식 클래스는 부모 클래스를 단 하나만 가질 수 있다.

  4. 생성자의 super(); 호출이 항상 먼저 선언 되는 것은
    상속의 부모클래스가 먼저 생성된다는 의미이다.
    그렇기 때문에 super();호출은 최상단에 되어야한다.

java 예제코드

public class Car {

    private String company;
    private String model;
    private int price;

    public Car() {
        System.out.println("부모");
    }

    public String getCompany() {
        return company;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public int discountPrice(int percentage) {
        return price - (price * percentage / 100);
    }
}

-------------------------------------------------------

public class HyundaiCar extends Car {
    private boolean premium;
}

-------------------------------------------------------

public class KiaCar extends Car{

    public KiaCar() {
        super(); // 생략가능.
        System.out.println("자식");
    }

    @Override
    public int discountPrice(int percentage) {
        return super.discountPrice(percentage);
    }

    public void test() {
        KiaCar kc = this;
        //자기 자신의 주소를 받아서 쓰고 싶을 때 쓴다.
    }
}

--------------------------------------------------------

public class ExtendsMain {

    public static void main(String[] args) {
        KiaCar kiaCar = new KiaCar();

        kiaCar.setPrice(3000000);

        System.out.println(kiaCar);
        System.out.println(kiaCar.getPrice());
        System.out.println(kiaCar.discountPrice(20));
    }
}

위의 코드에는 car라는 클래스에 현대 차와 기아 차가 공통적으로
가지고 있는 부모요소를 가지고 있고 그 클래스를 현대와 기아는 상속을 받는다
각각 상속을 받을 때 부모요소에 선언되어진 메소드는 각각의 자식 메소드에서
Override해서 쓸 수가 있다.
Override의 개념은 부모님이 자식에게 자동차를 물려 주었는데 그 자식은
그 자동차를 그대로 타고 다닐 수도 있고, 도색을 할 수도 있다.
하지만 그 자동차가 바뀌는 것은 아닌 개념을 말한다.

  • 실행 콘솔 화면


추상 클래스

추상 클래스란?

  • 어떠한 기능들이 모여있는 설계도라고 생각한다.
    직접 구현은 하지 않는 클래스

    • 메소드의 구현부가 사라진 추상 메소드가 있다.

추상클래스의 특징

  1. 추상 클래스는 생성자체를 할 수가 없다.

  2. 추상 메소드가 없어도 absctract를 붙여 추상클래스로 만들수 있다.

  3. 추상 메소드가 하나라도 있다면 추상클래스로 정의 해야한다.

  4. 추상 클래스는 일반 클래스가 가질 수 있는 것은 다 가질 수 있다.
    (생성자, 메소드, 멤버변수등)

  5. 클래스가 추상 클래스를 상속하게 된다면
    추상클래스 안에 있는 추상 메소드는 모두 오버라이드 해야한다. 혹은 그 상속받은 클래스를 추상클래스로 정의해야한다.

추상클래스 예제 코드

// 설계도라고 생각하면 된다.
public abstract class Transportation {

    // 추상메소드 ( abstract method )
    public abstract void go();

    public abstract void stop();
}

======================================

public class Taxi extends Transportation {

    @Override   // @ 시작하는 문법을 어노테이션이라 한다.
    public void go() {
        System.out.println("택시를 타고 출발");
    }

    @Override
    public void stop() {
        System.out.println("택시를 타고 도착");
    }

    public void checkTaxiNumber() {
        System.out.println("택시 번호 확인");
    }
}

=======================================

public class Subway extends Transportation {

    @Override
    public void go() {
        System.out.println("지하철을 타고 출발");
    }

    @Override
    public void stop() {
        System.out.println("지하철을 타고 도착");
    }

    public void checkRoute() {
        System.out.println("지하철 노선 확인");
    }
}
======================================

public class Airplane extends Transportation{

    @Override
    public void go() {

    }

    @Override
    public void stop() {

    }
}

===============================

public class Main {

    public static void main(String[] args) {
        Transportation transportation = new Taxi();
        transportation.go();
    }
}

위의 코드는 transportation이라는 교통수단
추상 클래스를 정의를 하고 각각 교통수단이 될 수 있는 클래스 taxi, subway, airplane등을
만들고 각각 transportation을 상속받는다.

  • 추상클래스는 바로 생성이 불가하기 때문에
    생성을 할 때 상속을 받는 일반 클래스를 생성해서 대입해준다.

  • 실행 콘솔 화면


오버라이드

  • 추상 메소드는 생성을 하지 않고 선언만 된 상태이다.

이 조건 때문에 실행부가 최초에 없다.
그렇기 때문에 직접 실행을 시키기 위해서는
일반 클래스에서 오버라이드해서 재정의를 해주는 개념이다.

★ 여기서 주의할 점은?

  • 메소드 오버로딩과 다르게 매개변수의 타입과 매개변수의 숫자, 순서 등이 동일해야하고 메소드 타입도 동일한 상태에서 실행부만 바뀌어야한다.

인터페이스

인터페이스란?

인터페이스는 도구의 개념이다. 그렇기 때문에 여러개를 받을 수 있다.

  • 인터페이스를 주로 쓰는 이유는 어떠한 객체를 만들 때 부속품이 되는 부분들을 인터페이스로 설계하게 된다.

예를 들어서 리모컨이라는 객체가 있다.
이 객체는 작동을 할 때 버튼을 누르면 작동을 하고, 배터리를 넣어야 전원이 들어오는 형태이다. 그렇기 때문에 리모컨은 버튼과 배터리는 필요한 형태이지만, 배터리는 굳이 리모컨에 꼭 들어갈 필요는 없으며 버튼 또한 굳이 리모컨에 있어야 할 필요가 없다 . 이러한 경우 인터페이스로 빼준다.

  • 상속과 다른점

    상속은 선생님이라는 객체가 있고, 학생이라는 객체가 있을 때 이 두가지의 공통점으로 사람이라는 객체가 선언이 되고, 이 사람이라는 곳에
    공통된 부분을 나누어 상속 받는 구조를 나타낼 수 있는데 선생님이자 사람인 거고, 학생이자 사람인 형태인데 인터페이스라는 것은 위의 리모컨 형태처럼 굳이 상호간에 한쪽은 꼭 필요하나 한쪽은 굳이 필요하지 않을 때 사용된다고 보면된다.

인터페이스의 특징

  • 인터페이스의 안의 메소드는 무조건 추상메소드이다.
  • 그렇기 때문에 abstract예약어가 생략되어있다.
  • 추상클래스와 달리 생성자나 구현객체를 쓸 수 없다.
  • 일반 변수를 선언할 수 없다. 단! 상수는 가질 수 있다.
  • 인터페이스는 final 과 abstract를 생략한다.

인터페이스 예제 코드

// 인터페이스의 안의 메소드는 무조건 추상메소드이다. 그래서  abstract 예약어가 붙지않는다.
// 추상 클래스와 달리 생성자나 구현객체 자체를 쓸 수 없다.
// 일반 변수를 가질 수 없다. 상수는 가질 수 있다.
public interface Calculator {

    // final 을 생략 할 수 있다. 일반 변수를 선언 할 수 없기 때문에!!
    public int ERROR = -9999999;

    public double plus(double x, double y);

    public double minus(double x, double y);

    // default 를 쓰면 일반 메소드를 선언할 수 있다.
    public default double multiplication(double x, double y) {
        return x * y;
    };

    public double division(double x, double y);
}

====================================

public abstract class Equipment {

    public abstract void powerOn();
    public abstract void powerOff();
}

====================================

public class GeneralCalculator extends Equipment implements Calculator{

    @Override
    public void powerOn() {
        System.out.println("일반 계산기 전원을 켭니다.");
    }

    @Override
    public void powerOff() {
        System.out.println("일반 계산기 전원을 끕니다.");
    }

    @Override
    public double plus(double x, double y) {
        System.out.println("일반 계산기에서 더하기 실행");
        return x + y;
    }

    @Override
    public double minus(double x, double y) {
        System.out.println("일반 계산기에서 빼기 실행");
        return x - y;
    }

    @Override
    public double multiplication(double x, double y) {
        return Calculator.super.multiplication(x, y);
    }

    @Override
    public double division(double x, double y) {
        System.out.println("일반 계산기에서 나누기 실행");
        if (x == 0 || y == 0) {
            return ERROR;
        }
        return x / y;
    }

}

=======================================

public class SmartPhone extends Equipment implements Calculator {

    @Override
    public void powerOn() {
        System.out.println("스마트폰 전원을 켭니다.");
    }

    @Override
    public void powerOff() {
        System.out.println("스마트폰 전원을 끕니다.");
    }


    @Override
    public double plus(double x, double y) {
        System.out.println("스마트폰에서 더하기 실행");
        return x + y;
    }

    @Override
    public double minus(double x, double y) {
        System.out.println("스마트폰에서 빼기 실행");
        return x - y;
    }

    @Override
    public double division(double x, double y) {
        System.out.println("스마트폰에서 나누기 실행");
        if (x == 0 || y == 0) {
            return ERROR;
        }
        return x / y;
    }
}

=================================
public class Computer implements Calculator{

    @Override
    public double plus(double x, double y) {
        return 0;
    }

    @Override
    public double minus(double x, double y) {
        return 0;
    }

    @Override
    public double multiplication(double x, double y) {
        return Calculator.super.multiplication(x, y);
    }

    @Override
    public double division(double x, double y) {
        if (x == 0 || y == 0) {
            return ERROR;
        }
        return x / y;
    }
}

==================================

public class Main {

    public static void main(String[] args) {
        Equipment[] equipments = new Equipment[2];

        equipments[0] = new GeneralCalculator();
        equipments[1] = new SmartPhone();

        Calculator calculator = new Computer();
        calculator.multiplication(5.0,4);

        System.out.println("모든 장비 전원 켜기");
        for (Equipment equip : equipments) {
            equip.powerOn();
        }
        System.out.println();

        System.out.println("모든 장비에서 10과 20을 더하기");
        for (Equipment equip : equipments) {
            Calculator cal = (Calculator) equip;
            double result = cal.plus(10, 20);
            System.out.println("결과: " + result);
        }
        System.out.println();

        System.out.println("모든 장비에서 0과 10을 나누기");
        for (Equipment equip : equipments) {
            Calculator cal = (Calculator) equip;
            double result = cal.division(10, 0);
            System.out.println("결과: " + result);
        }
        System.out.println();

        System.out.println("모든 장비 전원 끄기");
        for (Equipment equip : equipments) {
            equip.powerOff();
        }
        System.out.println();
    }
}

calculation이라는 계산기 인터페이스를 통해 일반계산기, 스마트폰의 계산기, 컴퓨터 계산기등으로 implements해서 기능들을 재정의 해서 쓰는 로직들이다.

  • 실행 콘솔 화면

profile
백엔드 개발자 준비중

0개의 댓글