[oop] 인터페이스 대 추상 클래스 (일반 OO)

최근에 인터페이스와 추상 클래스의 차이점에 대해 두 번의 전화 인터뷰가있었습니다. 나는 내가 생각할 수있는 모든 측면을 설명했지만 특정 내용을 언급하기를 기다리고있는 것 같으며 그것이 무엇인지 모르겠습니다.

내 경험으로는 다음과 같은 것이 사실이라고 생각합니다. 중요한 점이없는 경우 알려주십시오.

상호 작용:

인터페이스에 선언 된 모든 단일 메소드는 서브 클래스에서 구현되어야합니다. 인터페이스에는 이벤트, 대리자, 속성 (C #) 및 메서드 만 존재할 수 있습니다. 클래스는 여러 인터페이스를 구현할 수 있습니다.

추상 클래스 :

서브 클래스는 추상 메소드 만 구현해야합니다. Abstract 클래스는 구현과 함께 일반적인 메소드를 가질 수 있습니다. 추상 클래스는 이벤트, 대리자, 속성 및 메서드 옆에 클래스 변수를 가질 수도 있습니다. C #에서 다중 상속이 존재하지 않기 때문에 클래스는 하나의 추상 클래스 만 구현할 수 있습니다.

  1. 그 후, 면접관은 “추상적 인 방법으로 만 추상 클래스가 있다면 어떻게 될까요? 인터페이스와 어떻게 다릅니 까?”라는 질문을 내놓았습니다. 나는 대답을 몰랐지만 위에서 언급 한 상속이라고 생각합니까?

  2. 다른 면접관이 인터페이스 내부에 공용 변수가 있는지 여부를 물었습니다. 추상 클래스와는 어떻게 다릅니 까? 인터페이스 안에 공용 변수를 가질 수 없다고 주장했습니다. 나는 그가 듣고 싶은 것이 무엇인지 몰랐지만 만족하지 못했습니다.

참조 :



답변

귀하의 질문에 “일반 OO”에 대한 것이지만 실제로 이러한 용어의 .NET 사용에 초점을 맞추고있는 것 같습니다.

.NET (Java와 유사)에서 :

  • 인터페이스는 상태 또는 구현을 가질 수 없습니다
  • 인터페이스를 구현하는 클래스는 해당 인터페이스의 모든 메소드의 구현을 제공해야합니다.
  • 추상 클래스는 상태 (데이터 멤버) 및 / 또는 구현 (메소드)을 포함 할 수 있습니다.
  • 추상 클래스는 추상 메소드를 구현하지 않고 상속 될 수 있습니다 (이 파생 클래스는 추상 자체 임)
  • 인터페이스는 다중 상속 될 수 있으며 추상 클래스는 그렇지 않을 수 있습니다 (이것은 인터페이스가 abtract 클래스와 별도로 존재하는 주요한 구체적인 이유 일 수 있습니다. 일반 MI의 많은 문제를 제거하는 다중 상속 구현을 허용합니다).

일반적인 OO 용어로서 차이점을 반드시 명확하게 정의 할 필요는 없습니다. 예를 들어, 유사한 엄격한 정의를 보유 할 수있는 C ++ 프로그래머가 있습니다 (인터페이스는 구현을 포함 할 수없는 추상 클래스의 엄격한 서브 세트입니다). 일부는 기본 구현을 가진 추상 클래스가 여전히 인터페이스이거나 추상적이지 않다고 말할 수 있습니다. 클래스는 여전히 인터페이스를 정의 할 수 있습니다.

실제로, 공개 메소드가 개인 가상 메소드에 ‘고정’되는 비가 상 메소드 인 NVI (Non-Virtual Interface)라는 C ++ 관용구가 있습니다.


답변

공군에있을 때 나는 조종사 훈련을 받고 USAF (미국 공군) 조종사가되었습니다. 그 시점에서 나는 아무것도 날 수 없었으며 항공기 유형 훈련에 참석해야했습니다. 자격을 갖추면 파일럿 (Abstract 클래스)과 C-141 파일럿 (콘크리트 클래스)이었습니다. 제 임무 중 하나에서 추가 책임이있었습니다 : 안전 책임자. 이제 나는 여전히 조종사 였고 C-141 조종사 였지만 안전 책임자 임무도 수행했습니다 (ISafetyOfficer를 구현했습니다). 조종사는 안전 요원 일 필요가 없었으며 다른 사람들도 그렇게 할 수있었습니다.

모든 USAF 조종사는 공군 전체의 특정 규정을 준수해야하며 모든 C-141 (또는 F-16 또는 T-38) 조종사는 ‘USAF 조종사’입니다. 누구나 안전 책임자가 될 수 있습니다. 요약하면 다음과 같습니다.

  • 파일럿 : 추상 클래스
  • C-141 파일럿 : 콘크리트 클래스
  • ISafety Officer : 인터페이스

덧붙여 참고 : 이것은 코딩 권장 사항이 아니라 개념을 설명하는 데 도움이되는 비유였습니다. 아래의 다양한 의견을 참조하십시오. 토론은 흥미 롭습니다.


답변

그들이 찾고있는 답은 근본적 또는 OPPS 철학적 차이라고 생각합니다.

추상 클래스 상속은 파생 클래스가 추상 클래스의 핵심 속성과 동작을 공유 할 때 사용됩니다. 실제로 클래스를 정의하는 행동의 종류.

반면에 인터페이스 상속은 클래스가 주변 클래스 동작을 공유 할 때 사용되며, 반드시 파생 클래스를 정의 할 필요는 없습니다.

예를 들어. 자동차와 트럭은 자동차 추상 클래스의 많은 핵심 속성과 동작을 공유하지만, Driller 또는 PowerGenerators와 같은 비 자동차 클래스도 공유하고 반드시 자동차 또는 트럭을 정의하지는 않지만 배기 생성과 같은 주변 동작을 공유합니다. 따라서 Car, Truck, Driller 및 PowerGenerator는 모두 동일한 인터페이스 IExhaust를 공유 할 수 있습니다.


답변

요약 : 추상 클래스는 유사한 클래스의 클래스 계층 모델링 에 사용됩니다 (예 : 동물은 추상 클래스 일 수 있으며 Human, Lion, Tiger는 구체적인 파생 클래스 일 수 있음)

인터페이스는 클래스를 구현하는 클래스의 유형에 신경 쓰지 않는 2 개의 유사 / 비 유사 클래스 간의 통신에 사용됩니다 (예 : 높이는 인터페이스 속성 일 수 있으며 Human, Building, Tree로 구현 될 수 있습니다. 먹을 수 있는지 여부는 중요하지 않습니다) , 당신은 당신이 죽거나 무엇이든 수영 할 수 있습니다 .. 그것은 당신이 신장 (당신의 수업에서 구현)이 필요한 것만 중요합니다).


답변

몇 가지 다른 차이점이 있습니다.

인터페이스는 구체적으로 구현할 수 없습니다. 추상 기본 클래스가 가능합니다. 이를 통해 구체적인 구현을 제공 할 수 있습니다. 이를 통해 추상 기본 클래스가 실제로보다 엄격한 계약을 제공 할 수 있지만 인터페이스는 실제로 클래스 사용 방법 만 설명합니다. (추상 기본 클래스에는 비가 상 멤버가 동작을 정의하여 기본 클래스 작성자에게 더 많은 제어 권한을 부여 할 수 있습니다.)

클래스에서 둘 이상의 인터페이스를 구현할 수 있습니다. 클래스는 단일 추상 기본 클래스에서만 파생 될 수 있습니다. 인터페이스를 사용하는 다형성 계층 구조를 허용하지만 추상 기본 클래스는 허용하지 않습니다. 또한 인터페이스를 사용하는 의사 다중 상속이 가능합니다.

API를 중단하지 않고 v2 +에서 추상 기본 클래스를 수정할 수 있습니다. 인터페이스 변경으로 인해 변경이 발생했습니다.

[C # /. NET 특정] 추상 기본 클래스와 달리 인터페이스는 값 유형 (구조체)에 적용될 수 있습니다. 구조체는 추상 기본 클래스에서 상속 할 수 없습니다. 이를 통해 행동 계약 / 사용 지침을 가치 유형에 적용 할 수 있습니다.


답변

상속
자동차와 버스를 고려하십시오. 그들은 두 개의 다른 차량입니다. 그러나 여전히 스티어링, 브레이크, 기어, 엔진 등의 공통 속성을 공유
합니다. 상속 개념을 사용하면 다음과 같이 나타낼 수 있습니다.

public class Vehicle {
    private Driver driver;
    private Seat[] seatArray; //In java and most of the Object Oriented Programming(OOP) languages, square brackets are used to denote arrays(Collections).
    //You can define as many properties as you want here ...
}

이제 자전거 …

public class Bicycle extends Vehicle {
    //You define properties which are unique to bicycles here ...
    private Pedal pedal;
}

그리고 자동차 …

public class Car extends Vehicle {
    private Engine engine;
    private Door[] doors;
}

이것이 전부 상속 에 관한 것 입니다. 우리는 위에서 본 것처럼 객체를 더 간단한 기본 형식과 그 자식으로 분류하는 데 사용합니다.

추상 클래스

추상 클래스는 불완전한 객체입니다. 그것을 더 이해하기 위해 차량 비유를 다시 한번 생각해 봅시다.
차량을 운전할 수 있습니다. 권리? 그러나 다른 차량은 다른 방식으로 운전됩니다 … 예를 들어 자전거를 운전하는 것처럼 자동차를 운전할 수 없습니다.
그렇다면 차량의 주행 기능을 나타내는 방법은 무엇입니까? 차량의 종류를 확인하고 자체 기능으로 운전하는 것이 더 어렵습니다. 새로운 유형의 차량을 추가 할 때 Driver 클래스를 반복해서 변경해야합니다.
다음은 추상 클래스와 메소드의 역할입니다. 상속하는 모든 자식이이 함수를 구현해야 함을 나타 내기 위해 drive 메서드를 abstract로 정의 할 수 있습니다.
차량 클래스를 수정하면 …

//......Code of Vehicle Class
abstract public void drive();
//.....Code continues

자전거와 자동차는 또한 운전 방법을 지정해야합니다. 그렇지 않으면 코드가 컴파일되지 않고 오류가 발생합니다.
간단히 말해서. 추상 클래스는 일부 불완전한 함수를 가진 부분적으로 불완전한 클래스이며 상속되는 자식은 자체적으로 지정해야합니다.

인터페이스
인터페이스가 완전히 불완전합니다. 속성이 없습니다. 그들은 상속받은 아이들이 무언가를 할 수 있음을 나타냅니다 …
당신이 다른 유형의 휴대 전화를 가지고 있다고 가정하십시오. 그들 각각은 다른 기능을 수행하는 다른 방법을 가지고 있습니다. 예 : 사람에게 전화하십시오. 휴대 전화 제조업체가 수행 방법을 지정합니다. 여기서 휴대폰은 전화를 걸 수 있습니다. 즉, 전화를 걸 수 있습니다. 이것을 인터페이스로 표현해 봅시다.

public interface Dialable {
    public void dial(Number n);
}

여기서 다이얼 러블 제조업체는 번호를 다이얼하는 방법을 정의합니다. 당신은 전화 번호를 제공해야합니다.

// Makers define how exactly dialable work inside.

Dialable PHONE1 = new Dialable() {
    public void dial(Number n) {
        //Do the phone1's own way to dial a number
    }
}

Dialable PHONE2 = new Dialable() {
    public void dial(Number n) {
        //Do the phone2's own way to dial a number
    }
}


//Suppose there is a function written by someone else, which expects a Dialable
......
public static void main(String[] args) {
    Dialable myDialable = SomeLibrary.PHONE1;
    SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....

따라서 추상 클래스 대신 인터페이스를 사용하면 Dialable을 사용하는 함수 작성기는 속성에 대해 걱정할 필요가 없습니다. 예 : 터치 스크린 또는 다이얼 패드가 있습니까? 유선 전화 또는 휴대폰입니까? 전화 걸기 가능 여부 만 알면됩니다. Dialable 인터페이스를 상속 (또는 구현)합니까?

더 중요한 것은 언젠가 다이얼 러블을 다른 것으로 바꾸면

......
public static void main(String[] args) {
    Dialable myDialable = SomeLibrary.PHONE2; // <-- changed from PHONE1 to PHONE2
    SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....

다이얼 러블을 사용하는 기능이 다이얼 러블 인터페이스에 지정된 것 이외의 세부 사항에 의존하지 않으며 또한 불가능하기 때문에 코드가 여전히 완벽하게 작동하는지 확인할 수 있습니다. 둘 다 Dialable 인터페이스를 구현하며 이것이 기능에 관심을 갖는 유일한 것입니다.

인터페이스는 공통 기능을 공유하는 한 객체간에 상호 운용성을 보장하기 위해 개발자가 일반적으로 사용합니다 (전화 번호로 전화를 걸어야하는 한 유선 또는 휴대폰으로 변경할 수있는 것처럼). 요컨대, 인터페이스는 속성이없는 훨씬 단순한 버전의 추상 클래스입니다.
또한 원하는만큼 인터페이스를 구현 (상속) 할 수 있지만 단일 상위 클래스 만 확장 (상속) 할 수 있습니다.

더 많은 정보
추상 클래스와 인터페이스


답변

java이 질문에 대답하기 위해 OOP 언어로 간주 하면 Java 8 릴리스에서는 위의 답변 중 일부 내용이 더 이상 사용되지 않습니다. 이제 자바 인터페이스는 구체적인 구현으로 기본 메소드를 가질 수 있습니다.

Oracle 웹 사이트 는 클래스 interfaceabstract클래스의 주요 차이점을 제공합니다 .

다음과 같은 경우 추상 클래스 사용을 고려하십시오 .

  1. 밀접하게 관련된 여러 클래스간에 코드를 공유하려고합니다.
  2. 추상 클래스를 확장하는 클래스에는 많은 공통 메소드 또는 필드가 있거나 public 이외의 액세스 수정 자 (예 : 보호 및 개인)가 필요합니다.
  3. 비 정적 또는 최종이 아닌 필드를 선언하려고합니다.

다음과 같은 경우 인터페이스 사용을 고려하십시오 .

  1. 관련없는 클래스가 인터페이스를 구현할 것으로 기대합니다. 예를 들어, 많은 관련이없는 객체가 Serializable인터페이스 를 구현할 수 있습니다.
  2. 특정 데이터 유형의 동작을 지정하려고하지만 누가 그 동작을 구현하는지는 신경 쓰지 않습니다.
  3. 여러 유형의 상속을 활용하려고합니다.

간단히 말해서 사용하고 싶습니다

인터페이스 : 여러 관련없는 객체로 계약을 구현하려면

추상 클래스 : 여러 관련 개체간에 동일하거나 다른 동작을 구현하려면

명확한 방법으로 사물을 이해하기 위해 코드 예제를 살펴보십시오 . 인터페이스와 추상 클래스의 차이점을 어떻게 설명해야합니까?