Hoon222y

[1226-1] 추상화 / 인터페이스 /강결합/약결합/ 본문

코딩/교육

[1226-1] 추상화 / 인터페이스 /강결합/약결합/

hoon222y 2018. 12. 26. 22:32

<InheritanceTest>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class inheritanceTest {
 public static void main(String[] args) {
  Medic medic = new Medic();
  Marine marine = new Marine();
  
  // marine = medic    //는 에러, 서로다른 타입이기 때문에
  Human h1 = medic;    //부모타입 = 자식 객체, 업케스팅(upcasting)
  Human h2 = marine;
  
  // 관련이 없는 타입은 처리할 수 없으므로 타입안정성이 높아지게 된다. 
  // Human h3 = new Hydra();
  
  // 상속을 사용하는 이유
  // 기능적 : 코드의 재사용성
  // 디자인 : 서로 다른 타입을 동종의 타입으로 처리
 }
}
 
//자바 또는 c#, C++ 에서 메모리 구조가 같더라도 클래스의 이름이 다르면 이는 다른 타입이다.
//추상화 (abstract): 구체적인 타입으로부터 공통의 속성을 뽑아 내어 새로운 클래스를 생성하는 기법
class Human{}
//그리고 인간 종족을 설계하는 개발자는 Human 클래스를 상속하기로 약속한다.
class Medic extends Human{}
class Marine extends Human{}
cs

 상속을 사용하는 이유

1. 코드의 재사용성 

2. 서로 다른 타입을 동종의 타입으로 처리


추상화 : 구체적인 타입으로부터 공통의 속성을 뽑아내어 새로운 클래스를 생성하는 기법


<InterfaceTest>

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
public class interfaceTest {
  public static void main(String[] args) {
   Person p = new Person();
  
   Anycall a= new Anycall();
   p.usePhone(a,"0123456789");
  
   Cyon c= new Cyon();
   p.usePhone(c,"0123456789");  //인자가 Anycall 이라서 에러 발생
   //동일한 메서드지만 타입이 다르다. 따라서 함수 오버로딩(메서드 오버로딩) 
 }
}
 
//핸드폰과 사람 사이의 규약을 설정합니다. 
//abstract class phone{    //추상 메소드가 있으면 추상클래스로 작성해야함 (abstract) 
// public abstract void send(String n);
//}
//위에 코드와 같은 기능
//객체지향 프로그래밍에서 자식에 대한 어떠한 기능을 물려주는 용도가 아닌 어떤 기능의 구현을 
//강제하기 위해 사용되는 클래스를 인터페이스라고 한다. 
interface phone{
  void send(String n);
}
//Person 시스템이 제공하는 기능이라고 생각합니다.
//이제 모든 핸드폰 개발자 또는 설계자는 Phone을 생성하기로 약속한다. 
class Anycall implements phone{   //interface 를 쓰기위해 implements를 쓴다. 
          //위에 주석한 코드 하려면 extends 쓰고 
  public void send(String n) {
   System.out.printf("calling  %s with anycall\n" , n);
  }
}
class Cyon implements phone{
  public void send(String n) {
   System.out.printf("calling  %s with Cyon\n" , n);
  }
}
class Sky implements phone{
  public void send(String n) {
   System.out.printf("calling  %s with Sky\n" , n);
  }
}
// Person을 시스템이라고 생각합니다. 
// Person 클레스는 객체 지향의 5대 원칙중 하나인 OCP(Open Close Principle)를 만족하지 않는다.
// OCP를 만족하지 않는 이유는 Person 클래스가 핸드폰의 이름을 직접적으로 사용하기 떄문이다. 
// 이 때, 사람과 핸드폰은 강하게 결합되어 있다고 하여 강결합(tightly coupling)이라고 한다. 
// 이 문제를 해결하려면 사람과 핸드폰이 느슨하게 결합되어 있어야 하는데 이를 약결합(loosely coupling)이라고 한다.
// Person <---------------> cyon or anycall (x)
// Person <---->object<---> cyon or anycall (o)
// Person <---->phone<---> cyon or anycall 처럼 phone 으로 연결한다. 
class Person{
// public void usePhone(Anycall p, String n) {p.send(n);}
// public void usePhone(Cyon p, String n) {p.call(n);}  //힘수 오버로딩
 public void usePhone(phone p, String n) {p.send(n);}
}
// 상속 : 코드의 재사용성, 서로 다른 타입을 동종의 타입으로 처리 하기 위해 사용
// 부모 클래스 : 자신의 기능을 물려주기 위해서 사용
// 추상 클래스 : 자신의 기능을 물려주기 위함 + 특정 기능 구현을 강제 하기 위해 사용
// 인터페이스 : 특정 기능 구현을 강제하기 위해 사용
 
 
cs


원래는 각각의 브랜드마다(anycall, cyon 등) 53번째 줄에서 각각의 오버로딩 함수들을 선언해야만 했다. phone이라는 부모 클래스를 상속하여 문제를 해결할 수 있다. 16번째 줄에서 코드가 abstract로 선언이 되었기 때문에 class를 선언할 때 abstract로 선언을 하였다. 추상 메소드가 있으면 추상클래스로 선언해야 한다(abstract).

 하지만 이렇게 구연하면 문제가 발생한다. person class가 핸드폰의 이름을 직접적으로 언급하기 때문에 OCP 원칙을 지키기 못한다. 

이처럼 직접적으로 연결된 경우를 강결합(tightly coupling)이라고 한다. 

느슨하게 연결하는것을 약경합(loosely coupling) 이라고 한다. 


 하지만 이러한 반복적인 코드를 작성하는것이 아니라 interface 를 사용하여 문제를 해결할 수 있는 다른 방법이 있다. 53번째 줄처럼 인자를 phone으로 받아서 문제를 해결하면 된다.  phone 을 implements 하고 문제를 해결할 수 있다. 

인터페이스 : 자식에 대한 대한 어떠한 기능을 물려주는 것이 아닌 어떤 기능의 구현을 강제하기 위해 사용 되는 클래스 


부모 클래스 : 자신의 기능을 물려주기 위해서 사용

추상 클래스 : 자신의 기능을 물려주기 위함 + 특정 기능 구현을 강제하기 위해 사용

인터페이스 : 특정 기능 구현을 강제하기 위해 사용 

Comments