interface의 객체지향적 특성
포스트
취소

interface의 객체지향적 특성

interface가 갖는 특징들을 객체지향의 특성 네가지와 연관지어 보겠습니다.

💻 캡슐화

훌륭한 객체란 내부의 정확한 구현을 모른 채, interface만 알면 쉽게 상호작용할 수 있는 객체를 의미합니다. 이런 객체를 만들기 위해서는 객체 외부에서 접근할 수 있는 interface와 내부에 은닉화되는 구현을 명확히 분리해서 생각해야 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
interface Car {
    public void speedUp();
    public void speedDown();
}

class CarA implements Car {
    private void somethingBeforeSpeedUpA() {
        //
    }

    private void someThingBeforeSpeedDownA() {
        //
    }

    public void speedUp() {
        somethingBeforeSpeedUpA();
    }

    public void speedDown() {
        someThingBeforeSpeedDownA();
    }
}

class CarB implements Car {
    private void somethingBeforeSpeedUpB() {
        //
    }

    private void somethingBeforeSpeedDownB() {
        //
    }

    public void speedUp() {
        somethingBeforeSpeedUpB();
    }

    public void speedDown() {
        somethingBeforeSpeedDownB();
    }
}

위 예시에서 CarACarB는 관련있는 함수들로 이루어진 집단을 이루고 있으며(캡슐화), 속도를 낮추거나 올리기 전에 동작하는 함수들이 은닉화 되어 있습니다(정보은닉). 사용자는 속도를 조절하기 전에 각 자동차에서 동작하는 내부로직을 알 필요없이 interface에 있는 함수만 호출하면 됩니다.

💻 추상화

복잡도를 낮추기 위해 단순화하는 과정에서 객체들의 공통된 구현사항들을 interface로 분리할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
interface CaffeinBeverage {
    public void boilWater();
    public void brew();
    public void pourInCup();
    public void addCondiments();
}

class Tea implements CaffeinBeverage {
    public void boilWater() {
        System.out.println("차 물 끓이는 중");
    }

    public void brew() {
        System.out.println("찻 잎을 우려내는 중");
    }

    public void pourInCup() {
        System.out.println("찻 잔에 따르는 중");
    }

    public void addCondiments() {
        System.out.println("레몬을 추가하는 중");
    }
}

class Coffee implements CaffeinBeverage {
    public void boilWater() {
        System.out.println("커피 물 끓이는 중");
    }

    public void brew() {
        System.out.println("커피를 우려내는 중");
    }

    public void pourInCup() {
        System.out.println("커피잔에 따르는 중");
    }

    public void addCondiments() {
        System.out.println("설탕과 우유를 추가하는 중");
    }
}

💻 상속성

interface끼리는 다음과 같이 상속 할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
interface A {
    public void a();
}

interface B {
    public void b();
}

interface C extends A {
    public void c();
}

interface D extends A, B {
    public void d();
}

class Test1 implements C {
    public void a() {
        //
    }

    public void c() {
        //
    }
}

class Test2 implements D {
    public void a() {
        //
    }

    public void b() {
        //
    }

    public void d() {
        //
    }
}

💻 다형성

interface에 맞춰 프로그래밍을 할 때 가장 중요한 점은 다형성을 활용할 수 있다는 것입니다.
interface에 맞춰 구현하고자 하는 객체는 해당 interface를 상속 받게되고 이 때 interface는 상위 형식이 됩니다. 상위 형식을 상속 받은 객체의 인스턴스는 다형성에 따라 상위 형식의 타입을 가진 변수에 참조값을 대입할 수 있습니다. 이는 변수를 선언한 곳에서 실제 객체의 정확한 구현을 알 필요가 없음을 의미합니다.

1
2
3
4
5
Dog d = new Dog();
d.bark();

Cat c = new Cat();
c.meow();
1
2
3
4
5
Animal d = new Dog();
d.makeSound();

Animal c = new Cat();
c.makeSound();

위의 첫번째 예시는 interface에 맞춰 구현하지 않은 것이고, 두번째는 interface에 맞춰 구현한 것입니다. 첫번째 예시에서는 변수가 어떤 객체인지 알아야 하지만, 두번째는 알 필요없이 interface에 선언된 함수만 호출하면 됩니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.