인터페이스 또는 추상 클래스 : 어느 것을 사용해야합니까?


327

PHP를 사용해야 할 때 interface와 언제 사용해야하는지 설명해주세요 abstract class.

로 변경하려면 어떻게 abstract class해야 interface합니까?

답변:


458

시스템 (자체 포함)에서 작업하는 개발자가 빌드 할 클래스에서 일련의 메소드를 구현하도록하려면 인터페이스를 사용하십시오.

당신이 당신의 시스템에서 작업하는 개발자를 강제로 할 때 추상 클래스를 사용하여 메소드 세트 번호를 구현하기 위해 (자신을 포함) 당신은 그들의 자식 클래스를 개발하는 데 도움이됩니다 몇 가지 기본 방법을 제공하고자합니다.

명심해야 할 또 다른 사항은 클라이언트 클래스는 하나의 추상 클래스 만 확장 할 수있는 반면 여러 인터페이스를 구현할 수 있다는 것입니다. 따라서 추상 클래스에서 행동 계약을 정의하는 경우 각 하위 클래스는 단일 계약 만 준수 할 수 있습니다. 때로는 사용자 프로그래머에게 특정 경로를 따라 가고 싶을 때 좋은 일입니다. 다른 경우에는 나쁠 것입니다. PHP의 Countable 및 Iterator 인터페이스가 인터페이스 대신 추상 클래스인지 상상해보십시오.

(가 언급 한 바와 같이 당신이있는 거 확실 어떤 방법으로 갈 때 흔한 한 가지 방법 은 아래 클리 터스는 ) 인터페이스를 만든 다음 추상 클래스가 인터페이스를 구현하는 것입니다.


12
나는 하루 종일 사용법 abstractinterface수업 을 이해하려고 노력했지만 , 당신의 게시물은 그것을 명확하게했습니다. 감사합니다 Alan
afarazit

4
추상 클래스의 또 다른 장점은 추상 보호 메소드 를 정의 할 수 있다는 것입니다 . 항상 유용한 것은 아니지만 일부 아키텍처에서는 유용 할 수 있습니다.
netcoder

따라서 많은 경우에 우리는 유연성 때문에 추상 클래스를 사용해야합니다. – 이것이 내 결론입니다.)
ymakux

3
@volocuga : Alan이 지적한 것처럼 반드시 단일 초록 만 확장 할 수는 없습니다. 나는 개인적으로 추상이 인터페이스 아이디어를 구현하는 것을 좋아하지 않는다. 왜냐하면 코드 난독 화에 기여하고 덜 직접적인 IMO이기 때문이다.
Prefix

171

의 차이점 Abstract ClassInterface:

추상 클래스

추상 클래스는 수 몇 가지 기능을 제공 하고 파생 클래스의 나머지를 떠나 .

  • 파생 클래스 기본 클래스에 정의 된 구체적 함수를 무시하거나 무시할 수 있습니다 .

  • 추상 클래스에서 확장 된 자식 클래스는 논리적으로 관련되어야합니다.

상호 작용

인터페이스 에는 기능이 포함될 수 없습니다 . 그것은 단지 방법의 정의가 포함되어 있습니다.

  • 파생 된 클래스는 반드시 인터페이스에 정의 된 모든 메소드에 대한 코드를 제공해야합니다 .

  • 완전히 다른 클래스와 관련이없는 클래스는 인터페이스를 사용하여 논리적으로 그룹화 할 수 있습니다.


1
실례를 보여줄 수 있습니까?
RN Kushwaha

1
무슨 사이의 차이 abstract class X implements Yclass X implements Y?
웨 비난

3
@Webinan abstract class X implements Y여러분은 X의 대량 기능이 파생 클래스에서 구현되어야하고 추상 클래스와 파생 클래스 모두 Y에 정의 된 함수를 포함해야하고 클래스 X는 Y에 정의 된 함수를 포함해야 함을 선언 합니다class X implements Y . 인터페이스 Y XI 이외의 다른 클래스에 의해 구현되도록 의도 된 것이 아니며 실제로 Y를 인터페이스로 정의하는 것을 건너 뛰고 Y의 함수를 퍼블릭 / 보호 / 개인 추상 함수로 구현하여 파생 클래스에서 구현되도록합니다.
Calle Bergström

1
인터페이스가없는 유일한 방법의 정의를 포함, 그들은 또한 포함 할 수 있습니다 상수
Thielicious

당신의 비교를 좋아했습니다. 그래서 무언가를 추가하고 싶었습니다. 인터페이스는 즉시 클래스 상수를 가질 수 있지만 추상 클래스는 클래스 상수를 가질 수 없습니다.
노만 이브라힘

128

왜 추상 클래스를 사용해야합니까? 다음은 간단한 예입니다. 다음 코드가 있다고 가정 해 봅시다.

<?php 

class Fruit {
    private $color;

    public function eat() {
        // chew
    }

    public function setColor($c) {
        $this->color = $c;
    }
}

class Apple extends Fruit {
    public function eat() {
        // chew until core
    }
}

class Orange extends Fruit {
    public function eat() {
        // peeling
        // chew
    }
}

이제 나는 사과를주고 당신은 그것을 먹습니다. 어떤 맛이야? 사과 맛이나요.

<?php 
$apple = new Apple();
$apple->eat();

// Now I give you a fruit.
$fruit = new Fruit();
$fruit->eat();

그 맛은 어때? 글쎄, 그건 말이되지 않으므로 그렇게 할 수 없어야합니다. 이것은 Fruit 클래스를 추상적이고 내부의 eat 메소드로 만들어서 수행됩니다.

<?php 
abstract class Fruit {
    private $color;

    abstract public function eat(){}

    public function setColor($c) {
        $this->color = $c;
    }
}
?>

추상 클래스는 인터페이스와 비슷하지만 추상 클래스에서 메소드를 정의 할 수 있지만 인터페이스에서는 모두 추상입니다. 추상 클래스는 빈 메소드와 작동하는 / 콘크리트 메소드를 모두 가질 수 있습니다. 인터페이스에서 정의 된 함수는 본문을 가질 수 없습니다. 추상 수업에서는 가능합니다.

실제 예 :

<?php 
abstract class person {

    public $LastName;
    public $FirstName;
    public $BirthDate;

    abstract protected function write_info();
}

final class employee extends person{

    public $EmployeeNumber;
    public $DateHired;

    public function write_info(){
        //sql codes here
        echo "Writing ". $this->LastName . "'s info to emloyee dbase table <br>";   
    }
}

final class student extends person{

    public $StudentNumber;
    public $CourseName;

    public function write_info(){
        //sql codes here
        echo "Writing ". $this->LastName . "'s info to student dbase table <br>";
    }
}

///----------
$personA = new employee;
$personB = new student;

$personA->FirstName="Joe";
$personA->LastName="Sbody";

$personB->FirstName="Ben";
$personB->LastName="Dover";

$personA->write_info();
// Writing Sbody's info to emloyee dbase table
$personB->write_info();
// Writing Dover's info to student dbase table 

2
안녕하세요,이 답변은 형식이 지정된 방식으로 인해 다운 투표를 받았을 것입니다. 큰 코드 블록이 아닌 경우 (네 개의 공백이 코드 블록에 무언가를 만들어서 텍스트를 들여 쓰기하여 블록에서 꺼내십시오), 이것이 어딘가에서 복사하여 붙여 넣은 경우에 좋습니다 (그렇습니다) 그것들을 신용하는 것은 공손 할 것입니다.
Camilo Martin

9
나는 과일 모범적 인 사람을 위해 당신을 사랑합니다! 내가 PHP를 배우기 시작한 이래,이 exmaples 덕분에 많은 감사의 말을 전한다
Raheel

23
+1 What does that taste like? Well, it doesn't make much sense, so you shouldn't be able to do that.이제 초록을 알고 있습니다!
웨 비난

는 무엇을 않습니다 final할 키워드? 좋은 포스트, 감사합니다.
거스

1
@VineeshKalarickal Person 예제에서 이해하지 못하는 것은 1) 추상 클래스 Person 사용 (예와 같이); 2) Person을 표준 클래스로 작성하고 Employee 및 Student가 write_info () 메소드를 대체하도록하십시오.
Ferex

66

모범 사례는 인터페이스를 사용하여 계약 및 추상 클래스를 하나의 구현으로 지정하는 것입니다. 이 추상 클래스는 많은 상용구를 채울 수 있으므로 특정 구현을 사용하지 않고도 필요하거나 원하는 것을 재정 의하여 구현을 만들 수 있습니다.


37

이것을 믹싱에 던지기 위해 Cletus가 추상 클래스와 함께 인터페이스를 사용한다고 언급했듯이, 나는 종종 인터페이스를 사용하여 디자인 사고를 명확히합니다.

예를 들어 :

<?php
class parser implements parserDecoratorPattern {
    //...
}

이렇게하면 내 코드를 읽는 사람 (및 데코레이터 패턴이 무엇인지 아는 사람)은 a) 내 파서를 작성하는 방법과 b) 데코레이터 패턴을 구현하는 데 사용되는 방법을 알 수 있습니다.

또한 Java / C ++ / etc 프로그래머가 아닌 기본이 될 수 있지만 여기에서 데이터 유형을 사용할 수 있습니다. 당신의 객체는 유형이며, 당신이 객체를 전달할 때 프로그래밍 방식으로 문제가됩니다. 계약 가능 항목을 인터페이스로 이동하면 메소드가 리턴하는 유형 만 지시하지만이를 구현하는 클래스의 기본 유형은 아닙니다.

늦었고 더 나은 의사 코드 예제를 생각할 수는 없지만 다음과 같습니다.

<?php
interface TelevisionControls {};
class Remote implements TelevisionControls {};
class Spouse implements TelevisionControls {};
Spouse spouse = new Spouse();
Remote remote = new Remote();
isSameType = (bool)(remote == spouse)

1
정말 멋진 예입니다! ;)
Joel Murphy

@ matt2000 성 차별이 아니며 동성 결혼에도 적용됩니다. 훌륭한 편집. :)
Austen Hoogen

4
이것은 멋진 예입니다! 그러나 나는 당신이 추상 클래스를 인스턴스화 할 수 있다고 생각하지 않지만 추상 클래스에서 확장되는 클래스
Arielle Nguyen

2
sudo 코드를 적어도 문제의 언어처럼 보이도록 죽일 수는 없습니다. 누군가 거기에 약간의 $를 넣어야합니다.
나는 곰 한 번 씨름했다.

2
이 예제는 재미 있지만 추상 클래스를 직접 인스턴스화 할 수는 없습니다. 사람들이 PHP에서 올바른 사용법으로 간주하지 않도록 예제를 변경하십시오.
saji89

16

가장 큰 차이점은 추상 클래스는 기본 구현을 포함 할 수 있지만 인터페이스는 불가능하다는 것입니다.

인터페이스는 구현없이 동작 계약입니다.


16

또한 다른 OO 언어에 일종의 인터페이스와 추상화가 있다고해서 PHP와 동일한 의미와 목적을 갖는 것은 아닙니다. PHP의 인터페이스에는 실제로 실제 기능이 없지만 추상화 / 인터페이스 사용은 약간 다릅니다. 시맨틱 및 스킴 관련 이유로 사용됩니다. 요점은 개발자가 나중에 완전히 다른 사용 계획을 가지고 있는지 여부에 관계없이 향후 확장을 위해 가능한 한 유연하고 확장 가능하며 안전한 프로젝트를 만드는 것입니다.

영어가 모국어가 아닌 경우 추상화 및 인터페이스가 실제로 무엇인지 찾아 볼 수 있습니다. 동의어도 찾으십시오.

그리고 이것은 당신을 은유로 도울 수 있습니다.

상호 작용

딸기로 새로운 종류의 케이크를 굽고 재료와 단계를 설명하는 레시피를 만들었습니다. 왜 맛이 좋으며 손님이 좋아하는지 알 수 있습니다. 그런 다음 다른 사람들도 그 케이크를 맛볼 수 있도록 레시피를 게시하기로 결정했습니다.

여기 요점은

-제대로 만들기 위해
-조심스럽게
-너무 많은 딸기 나 다른 것들과 같이 나빠질 수있는 것들을 막기 위해
-그것을 시도하는 사람들을 위해 쉽게 유지하기
-얼마나 오래해야 할지를 말해주는 것 )
-할 수 있지만 할 수없는 일을 말하십시오.

정확하게 THIS는 인터페이스를 설명합니다. 가이드, 레시피의 내용을 관찰하는 일련의 지침입니다. PHP로 프로젝트를 생성하고 GitHub 또는 동료와 함께 코드를 제공하려는 경우와 동일합니다. 인터페이스는 사람들이 할 수있는 것과하지 말아야 할 것입니다. 그것을 지키는 규칙-하나를 불순종하면 전체 구조물이 파손됩니다.


추출

여기에서이 은유를 계속하려면 ... 이번에는 그 케이크를 먹는 손님이라고 상상해보십시오. 그럼 당신은 지금 레시피를 사용하여 그 케이크를 시도하고 있습니다. 그러나 레시피에 설명 된 단계를 새 재료를 추가하거나 변경 / 건너 뛰기를 원합니다. 그럼 다음은 무엇입니까? 그 케이크의 다른 버전을 계획하십시오. 이번에는 스트로 베리가 아닌 검은 딸기와 더 많은 바닐라 크림이 있습니다.

이것이 원래 케이크의 확장을 고려할 수있는 것입니다. 기본적으로 릴과 다르기 때문에 새로운 레시피를 생성하여 추상화를 수행합니다. 몇 가지 새로운 단계와 다른 재료가 있습니다. 그러나 블랙 베리 버전에는 원본에서 가져온 부분이 있습니다. 이것은 모든 종류의 케이크가 가져야하는 기본 단계입니다. 우유처럼 재료처럼-그것은 모든 파생 클래스가 가진 것입니다.

이제 재료와 단계를 교환하고 싶다면 반드시 그 케이크의 새 버전에서 정의해야합니다. 이것들은 새로운 케이크에 대해 정의되어야하는 추상적 인 방법 입니다. 케이크에 과일이 있어야하는데 어떤 것이 있습니까? 이번에는 검은 딸기를 먹습니다. 끝난.

거기에서 케이크를 확장하고 인터페이스와 추상 단계 및 재료를 따랐습니다.


1
이것은 PHP와 관련된 것을 내가 가장 좋아하는 비교였습니다. 정말 말이되었습니다. 감사합니다!
cbloss793

13

이미 훌륭한 답변 중 일부에 추가하려면 다음을 수행하십시오.

  • 추상 클래스를 사용하면 어느 정도의 구현을 제공 할 수 있으며 인터페이스는 순수한 템플릿입니다. 인터페이스는 기능 만 정의 할 수 있으며 구현할 수 없습니다.

  • 인터페이스를 구현하는 모든 클래스는 자신이 정의한 모든 메소드를 구현하기 위해 커밋하거나 추상으로 선언해야합니다.

  • 인터페이스는 Java와 같이 PHP가 다중 상속을 지원하지 않는다는 사실을 관리하는 데 도움이 될 수 있습니다. PHP 클래스는 단일 부모 만 확장 할 수 있습니다. 그러나 원하는만큼 인터페이스를 구현하도록 클래스 약속을 할 수 있습니다.

  • type : 구현하는 각 인터페이스마다 클래스가 해당 유형을 사용합니다. 모든 클래스는 인터페이스 (또는 더 많은 인터페이스)를 구현할 수 있으므로 인터페이스는 관련이없는 유형을 효과적으로 조인합니다.

  • 클래스는 수퍼 클래스를 확장하고 여러 인터페이스를 구현할 수 있습니다.

    class SubClass extends ParentClass implements Interface1, Interface2 {
        // ...
    }

인터페이스를 사용해야 할 때와 추상 클래스를 사용해야 할 때를 알려주세요.

구현이없는 템플릿 만 제공해야하는 경우 인터페이스를 사용하고 해당 인터페이스를 구현하는 모든 클래스가 해당 클래스를 구현하는 다른 클래스와 동일한 메서드를 갖도록해야합니다.

다른 객체 (부분적으로 빌드 된 클래스)의 기초를 만들려면 추상 클래스를 사용하십시오. 추상 클래스를 확장하는 클래스는 정의 / 구현 된 일부 속성 또는 메서드를 사용합니다.

<?php
// interface
class X implements Y { } // this is saying that "X" agrees to speak language "Y" with your code.

// abstract class
class X extends Y { } // this is saying that "X" is going to complete the partial class "Y".
?>

추상 클래스를 인터페이스로 변경하려면 어떻게해야합니까?

다음은 간단한 사례 / 예입니다. 구현 세부 사항을 모두 제거하십시오. 예를 들어, 추상 클래스를 다음에서 변경하십시오.

abstract class ClassToBuildUpon {
    public function doSomething() {
          echo 'Did something.';
    }
}

에:

interface ClassToBuildUpon {
    public function doSomething();
}

12

철학적 관점에서 :

  • 추상 클래스는 "is"관계를 나타냅니다. 과일을 가지고 있다고하자. 일반적인 책임과 행동을 공유하는 과일 추상 클래스가 있습니다.

  • 인터페이스는 "해야 할"관계를 나타냅니다. 내 의견으로는 (주니어 개발자의 의견 인) 인터페이스는 행동 또는 행동과 가까운 것으로 이름을 붙여야합니다 (죄송합니다, 나는 영어를 모국어로 사용하지 않습니다) IEatable이라고 말하십시오. 당신은 그것이 먹을 수 있다는 것을 알고 있지만, 당신이 무엇을 먹는지 모릅니다.

코딩 관점에서 :

  • 객체에 코드가 중복 된 경우 이는 일반적인 동작이 있음을 나타내므로 인터페이스를 사용하여 코드를 재사용 할 수없는 추상 클래스가 필요할 수 있습니다.

  • 또 다른 차이점은 객체가 필요한만큼 많은 인터페이스를 구현할 수 있지만 "다이아몬드 문제"로 인해 하나의 추상 클래스 만 가질 수 있다는 것입니다 (이유를 확인하려면 여기를 확인하십시오! http://en.wikipedia.org/wiki/ Multiple_inheritance # The_diamond_problem )

아마도 몇 가지 요점을 잊었을 수도 있지만, 명확하게 이해할 수 있기를 바랍니다.

추신 : "는"/ "해야한다"는 Vivek Vermani의 답변에 의해 가져옵니다. 나는 그의 답변을 훔치려는 것이 아니 었습니다.


2
당신이 찾고있는 단어는 먹을 수 있습니다.
트래비스 웨스턴

1
사실, 나는 그 단어가 "동사", "행하는 단어"라고 생각합니다
Grizly

7

추상 클래스와 인터페이스의 기술적 차이점은 이미 다른 답변에 정확하게 나와 있습니다. 객체 지향 프로그래밍을 위해 코드를 작성하면서 클래스와 인터페이스 중에서 선택하는 설명을 추가하고 싶습니다.

클래스는 엔티티를 나타내야하지만 인터페이스는 동작을 나타냅니다.

예를 들어 봅시다. 컴퓨터 모니터는 엔터티이며 클래스로 표현해야합니다.

class Monitor{
    private int monitorNo;
}

디스플레이 인터페이스를 제공하도록 설계되었으므로 기능은 인터페이스로 정의해야합니다.

interface Display{
    void display();
}

다른 답변에서 설명한 것처럼 고려해야 할 다른 것들이 많이 있지만, 이것이 코딩하는 동안 대부분의 사람들이 무시하는 가장 기본적인 것입니다.


2
PHP는 리턴 타입을 정의하지 않고 OP는이 질문에 태그를 달았습니다PHP
Purefan

1

둘 다 사용해야 할 때의 예를 추가하고 싶었습니다. 현재 범용 ERP 솔루션에서 데이터베이스 모델에 바인딩 된 파일 핸들러를 작성 중입니다.

  • 표준 crud를 처리하는 여러 추상 클래스와 여러 범주의 파일에 대한 변환 및 스트리밍과 같은 특수 기능이 있습니다.
  • 파일 액세스 인터페이스는 파일을 가져오고 저장하고 삭제하는 데 필요한 공통 메소드 세트를 정의합니다.

이런 식으로, 서로 다른 파일을위한 여러 템플릿과 명확한 구별을 가진 공통 인터페이스 메소드 세트를 갖게됩니다. 이 인터페이스는 기본 추상 클래스와 달리 액세스 방법에 대한 올바른 비유를 제공합니다.

다른 파일 스토리지 서비스에 대한 어댑터를 만들 때 줄을 따라 가면이 구현을 통해 완전히 다른 컨텍스트에서 인터페이스를 다른 곳에서 사용할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.