구체적 Vs 추상적 Vs 인터페이스 - [OOP & 자바#4]

15875 단어 oopjavacomputerscience
구체류, 추상류와 인터페이스 간의 관계를 탐구합시다.
만약 우리가 노트북 컴퓨터를 만들려고 한다면
class Laptop {
  String screen;
  int batteryHour;

  Laptop(String screen, int batteryHour) {
    this.screen = screen;
    this.batteryHour = batteryHour;
  }

  void moveCursor(){
    System.out.println("Using the trackpad to move the cursor");
  }
}
Laptop클래스는 화면 해상도를 나타내는 문자열과 배터리가 사용할 수 있는 시간을 나타내는 정수를 포함하는 구조 함수를 포함한다.그것은 뒤에 설명할 수 있는 moveCursor 방법이 하나 더 있다.
Laptop ex1 = new Laptop("1080P",5);
Laptop ex2 = new Laptop("4k", 8);
우리가 자주 직면하는 전형적인 문제는, 때때로 우리는 기존의 대상과 관련된 것, 예를 들어 이 예의 데스크톱을 만들어야 한다는 것이다.
데스크탑에도 화면이 있다는 점을 감안하여 다음과 같이 노트북 클래스를 데스크탑 클래스의 상위 클래스로 간단명료하게 만들 수 있습니다.
class Desktop extends Laptop {
  Desktop(String screen, int batteryHour){
    super(screen, batteryHour);
  }
}
만약 당신이 이라는 책을 읽었다면 시스템 1이나 우리 뇌의 게으르고 빠른 반응 시스템이 자주 실수를 범한다는 것을 알게 될 것이다.
이것이 바로 이런 예다.따라서 어떤 상황에서도 대상이 특정한 속성을 공유한다고 해서 하위 분류화하지 말아야 한다.이러한 솔루션이 LSP(Liskov 대체 원칙)를 위반할 수 있는 이유는 여러 가지가 있습니다.뚜렷한 문제batteryHour는 aDesktop에게 의미가 없다는 것이다.
노트북과 데스크톱은 모두 컴퓨터다.그들은 비슷한 점이 많다.그러나 데스크탑이 노트북이라고 말하지 않고, 반대로도 마찬가지라는 내 의견에 동의할 것이다.이것은 그들이 친자 관계에 적합하지 않다는 것을 설명한다.

콘크리트류
모두 컴퓨터인 것을 알고 우리는 첫 번째 효과적인 설계를 찾았다.
// Have Computer as a Concrete parent class
class Computer {
  String screen;
  void moveCursor(){
    System.out.println("moving the cursor?");
  }
}

class Laptop extends Computer {
  int batteryHour;
  Laptop(String screen, int batteryHour) {
    super.screen = screen;
    this.batteryHour = batteryHour;
  }

  @Override
  void moveCursor(){
    System.out.println("Using the trackpad to move the cursor");
  }
}

class Desktop extends Computer {
  Desktop(String screen){
    super.screen = screen;
  }

  @Override
  void moveCursor(){
    System.out.println("Using the mouse to move the cursor");
  }   
}
관찰하다.
  • Computer클래스를 이 두 부류
  • 의 부류로 정의한다
  • 흔히 볼 수 있는 속성과 방법에 대해 부류에서 추출해야 한다.
  • 방법은 하위 클래스 간에 공유할 수 있으며 이를 상위 클래스에 포함시켜 모든 하위 클래스가 이러한 방법을 가지고 있음을 확보할 수 있다.그러나 우리는 부류 단계에서 정확한 작성 방법을 실현할 수 없을 수도 있다.이것은 모든 하위 클래스가 자신의 실현을 포함하기 위해 이 방법을 다시 써야 한다는 것을 의미한다.이 동작은 컴파일러가 강제로 실행하는 것이 아닙니다. 이것은 컴파일러 방법을 다시 쓸 때 컴파일러 방법을 잊어버리면 의외의 실행 중 오류가 발생할 수 있음을 의미합니다.예를 들어 데스크톱 사용자는 일반적으로 터치보드를 사용하여 커서를 제어하지 않는다.따라서 moveCursor 방법은 Desktop의 하위 클래스에서 다시 써야 한다.그러나 재작성을 생략하는 것은 컴파일러가 완전히 받아들일 수 있는 행위이다.
  • 부류도 구체적이기 때문에 실례화할 수 있다.그러나 이렇게 하는 것은 무의미할 수도 있다.우리의 예에서 만약 우리가 호출new Computer().moveCursor()을 한다면 출력은 의미가 없을 수도 있다.

  • 추상류
    두 번째 방법은 Computer를 추상류로 만드는 것이다.
    abstract class Computer {
      String screen;
      abstract void moveCursor();
    }
    
    class Laptop extends Computer {
      int batteryHour;
      Laptop(String screen, int batteryHour) {
        super.screen = screen;
        this.batteryHour = batteryHour;
      }
    
      @Override
      void moveCursor(){
        System.out.println("Using the trackpad to move the cursor");
      }
    }
    
    class Desktop extends Computer {
      Desktop(String screen){
        super.screen = screen;
      }
    
      @Override
      void moveCursor(){
        System.out.println("Using the mouse to move the cursor");
      }   
    }
    

    추상류
  • 인스턴스화할 수 없음
  • 에 포함된 추상적인 방법은 세부 사항을 실현하지 못하고 하위 클래스에 의해 이루어져야 하며 컴파일러
  • 에 의해 강제로 실행됩니다
  • 속성 포함
  • 실현의 구체적인 방법
  • 도 포함할 수 있다
    이것은 기본적으로 우리가 구체적인 과정에서 직면한 몇 가지 문제를 해결했다.부류를 실례화할 필요가 없다면 부류를 추상화하는 것이 통상적으로 더 좋다고 확신할 수 있다.현재 두 번째 방법의 단점 (적어도 자바에 대해서 말하자면) 은 하나의 클래스는 하나의 부모 클래스에서만 계승할 수 있다는 것이다.
    충전할 수 있는 물체에 사용할 Chargeable 종류를 원한다면:
    abstract class Chargeable {
      abstract Chargeable charge();
    }
    
    그럼 넌 딜레마에 직면하게 될 거야.가령 하나의 클래스가 하나의 부류만 부류화할 수 있다고 가정한다면 어떤 종류를 선택합니까?

    다중 계승에 대한 방주
  • 당신은 서로 다른 부급의 모든 방법을 계승하기를 원할 수 있지만 모든 속성은 아닙니다.
  • 당신에게 PineapplePen는 논리적인 대상이 될까요?
  • class PineapplePen extends Pineapple, Pen{
    //...
    }
    

    이음매
    다음 옵션은 인터페이스입니다.
    abstract class Computer {
      String screen;
      abstract void moveCursor();
    }
    
    interface Chargeable {
      void charge();
    }
    
    class Laptop extends Computer implements Chargeable {
      int batteryHour;
      Laptop(String screen, int batteryHour) {
        super.screen = screen;
        this.batteryHour = batteryHour;
      }
    
      @Override
      void moveCursor(){
        System.out.println("Using the trackpad to move the cursor");
      }
    
      @Override
      public void charge(){
        // pretend that it does something
        System.out.println("Charging the laptop");
      }
    }
    
    class Desktop extends Computer implements Chargeable {
      Desktop(String screen){
        this.screen = screen;
      }
    
      @Override
      void moveCursor(){
        System.out.println("Using the mouse to move the cursor");
      }
    
      @Override
      public void charge(){
        // pretend that it does something
        System.out.println("Providing power to the desktop");
      }
    }   
    
    인터페이스에는 다음과 같은 특징이 있습니다.
  • 방법은 은밀하고 추상적이며 공개적이다
  • 인스턴스화할 수 없음
  • 인터페이스
  • 에서 상수 변수만 허용(정적 최종)
  • 인터페이스를 통해 여러 인터페이스 확장 가능
  • 클래스당 다중 인터페이스 가능
  • 마지막 코드에는 구체적인 클래스, 추상적인 클래스와 인터페이스의 조합이 있다.둘 사이에는 우세가 없다.반대로 그 중 가장 도움이 되는 상황을 탐색하는 것은 프로그램을 설계할 때 우리의 옵션을 평가하고 정확한 옵션을 선택할 수 있도록 지식을 제공할 것이다.

    요약
    콘크리트류
    추상류
    이음매
    구현
    리얼
    실제 요약
    요약
    실례화 가능
    예, 그렇습니다.
    아니오.
    아니오.
    다음까지...

    좋은 웹페이지 즐겨찾기