TIL - day5

정상화·2023년 2월 24일

TIL

목록 보기
2/46
post-thumbnail

구성

상속만으로 문제를 해결하려 하면 복잡한 상속구조를 가지게 되는 것이 부지기수.
이러한 문제를 피하기 위해 구성을 활용한다.

예시

abstract class 오리{
	public void 날기(){
    	System.out.println("납니다");
    }
    
    public void 헤엄치기(){
    	System.out.println("헤엄칩니다.");
    }
}

class 청둥오리 extends 오리{
}

class 고무오리 extends 오리{
	public void 날기(){
    	System.out.println("못 날아요");
    }
    
    public void 헤엄치기(){
    	System.out.println("그냥 떠요.");
    }
}

위와 같은 상속 구조를 가질 때 하늘을 날면서 그냥 떠다니는 로켓오리를 추가하고 싶다고 하자.
그럼 로켓오리는 오리 추상클래스를 바로 상속받아야 할까 아니면 고무오리를 상속받아야 할까.

구성을 통해 이 딜레마를 해결할 수 있다.

abstract class 오리{
     Wing wing;
     Leg leg;

    public void 날기(){
        wing.fly();
    }

    public void 헤엄치기(){
        leg.swim();
    }
}

class 청둥오리 extends 오리{
    public 청둥오리(){
        wing = new RealWing();
        leg = new RealLeg();
    }
}

class 고무오리 extends 오리{
    public 고무오리(){
        wing = new FakeWing();
        leg = new FakeLeg();
    }
}

class 로켓오리 extends 오리{
    public 로켓오리(){
        wing = new RealWing();
        leg = new FakeLeg();
    }
}

abstract class Wing{
    abstract public void fly();
}

class RealWing extends Wing{
    public void fly(){
        System.out.println("납니다");
    }
}

class FakeWing extends Wing{
    public void fly(){
        System.out.println("못 날아요");
    }
}

abstract class Leg{
    abstract public void swim();
}

class RealLeg extends Leg{
    public void swim(){
        System.out.println("헤엄칩니다.");
    }
}

class FakeLeg extends Leg{
    public void swim(){
        System.out.println("그냥 떠요");
    }
}

위와 같이 하면 원하는 속성을 가지면서도 각 오리가 가지는 속성의 중복을 해결할 수 있다.
해엄칠 때의 문구를 바꾸고 싶으면 RealLeg의 swim() 메서드를 수정하면 된다.

인터페이스

인터페이스는 모든 메서드가 추상메서드인 클래스이다.
인터페이스는 특이하게 다중 상속이 가능하며 방법은 다음과 같다.

예시

interface Interface1{
    void method1();
}

interface Interface2{
    void method2();
}

class Impl implements Interface1, Interface2 {
    @Override
    public void method1() {
        int a = 7;
    }

    @Override
    public void method2() {
        int a = 7;
    }
}

예외

프로그램 실행 중에 예외가 발생했을 때 이를 어떻게 처리할 지 정의할 수 있다.

public class Main {
    public static void main(String[] args) {
//        divideByZero(1);
        divide(1, 0);
    }

    private static void divideByZero(int a) throws ArithmeticException {
        int q = a / 0;
    }

    private static void divide(int a, int b) {
        try {
            int q = a / b;
        } catch (ArithmeticException e) {
            System.out.println("0으로 나누지 마시오");
        }
    }
}

divideByZero 메서드는 뒤에 throws ArithmeticException이라는 구문이 더 붙는다. 이는 이 메서드가 해당 예외를 발생시킬 수도 있음을 divideByZero를 호출한 사람에게 알리는 것이다. 이 경우 main 함수가 이 예외를 처리하는 책임을 갖게 된다.

아래 divide 함수는 try catch 구문을 이용해서 예외를 직접 처리한다. 만약
위의 코드를 실행시킨다면 int b는 0이 될 것이고 예외가 catch구문에 걸려서

"0으로 나누지 마시오"

라는 문구가 출력될 것이다.

profile
백엔드 희망

0개의 댓글