PHP에 왜 인터페이스가 있습니까?


35

PHP5부터 인터페이스가 언어에 추가되었습니다. 그러나 PHP는 너무 느슨하게 입력 되었기 때문에 인터페이스 사용의 이점이 대부분 손실되는 것 같습니다. 왜 언어에 포함되어 있습니까?


5
정답은 왜 아닐까요?
Alberto Fernández

5
그들이 혜택을 제공하지 않는 것 같아서 왜 포함시켜야합니까?
GSto

4
@HorusKol과 구현되기 전에는 사용되지 않았기 때문에 이전 버전보다 사용되지 않고 쓸모가없는 방법을 확인할 수 있습니다. 또한 사용이 유용하다는 말을 개선하는 주장을하고지지해야합니다.
Rein Henrichs

6
@HorusKol 전혀 불분명합니다. 해머의 가치 제안을 쉽게 설명 할 수 있습니다. 이 질문은 PHP 인터페이스의 가치 제안을 논증하는 것만이 아니라 PHP 인터페이스의 가치 제안을 보여줄 것을 요구합니다.
Rein Henrichs

3
인터페이스는 타이핑에만 국한된 것이 아니라는 점을 기억하십시오. 인터페이스는 구현 클래스 가 배치 하는 메소드 포함 해야 한다는 계약 입니다. 플러그인 엔진과 같은 것들에 유용합니다.
Michael

답변:


30

PHP에서 인터페이스의 주요 장점은 클래스가 여러 인터페이스를 구현할 수 있다는 것입니다. 이를 통해 일부 기능을 공유하지만 부모 클래스를 반드시 공유 할 필요는없는 클래스를 그룹화 할 수 있습니다. 일부 예에는 특정 방식으로 클래스의 캐싱, 출력 또는 액세스 속성이 포함될 수 있습니다.

코드에서 클래스 이름을 확인하는 대신 클래스가 지정된 인터페이스를 구현하는지 확인할 수 있습니다. 그런 다음 새 클래스를 추가해도 코드가 계속 작동합니다.

PHP는 http://php.net/manual/en/reserved.interfaces.php 와 같은 다양한 상황에서 유용 할 수있는 미리 정의 된 인터페이스를 제공합니다 .

편집-예제 추가

MyInterface라는 인터페이스가 있고 일부 기능을 공유하거나 공유하지 않을 수있는 다른 클래스의 여러 객체로 작업하는 경우 인터페이스를 통해 다음과 같은 작업을 수행 할 수 있습니다.

// Assume $objects is an array of instances of various classes
foreach($objects as $obj) {
 if($obj instanceof MyInterface) {
     $obj->a();
     $obj->b();
     $obj->c();
   }
}

23
즉 "당신이 완전히 동적으로 입력 된 언어의 모든 이점을 무시할 수 있습니다"
카밀 Tomšík

11
@Kamil, 나는 원하지 않는 단점을 겪지 않고 정적 타이핑의 이점을 활용할 수 있다고 생각합니다.
Karl Bielefeldt

9
진심 이세요? 대신에? 만약 그렇다면, 그때면 그리고 그때라면, 그것은 익숙하지 않습니까? 아, 예, 절차 적 프로그래밍.
Kamil Tomšík

23
@Kamil Tomšík 또 다른 무능하게 PHP를 사용하는 사람들이 아니라 PHP의 언어를 모욕한다. PHP에는 완전한 객체 지향 프로그래밍을위한 모든 도구가 있습니다. 사용 여부는 프로그래머가 결정합니다. 또한 절차 적 프로그래밍 자체에는 아무런 문제가 없습니다.
로터스 노트

18
@ Kamil-당신의 의견을 읽음으로써 OOP에 if-s가 없으며 어떻게 든 마술처럼 작동한다는 결론에 도달 할 수 있습니다. 와우.
Michael JV

23

PHP는 느슨하게 입력되었지만 메소드 매개 변수와 같은 것에 대해서는 강력하게 입력 할 수 있습니다.

다음 예제를 고려하십시오.

interface Car { function go(); }

class Porsche { function go() {} }

function drive(Car $car) {}

$porsche = new Porsche();

drive($porsche);

위의 코드는 다음과 같이 출력됩니다.

drive ()에 전달 된 인수 1은 주어진 Cars, Porsche의 인스턴스를 구현해야합니다.


1
물론, 너무 나쁘다. null그러나 매개 변수 의 기본값을 가질 수 있습니다 .
Emanuil Rusev

5
하지만 만약 drive을 필요로 Car하고 전달하는 것은 null... 매우 도움이 어쨌든되지 않을 것
HorusKol

7
null을 전달하지 마십시오. "특수 사례"개체를 사용하십시오 (Google for Martin Fowler의 설명).
Martin Blore

2
@Renesis 기본값을 null로 설정하면 형식 힌트 메서드에 null을 전달할 수 있습니다. (CAR $ car = null)을 사용하면 인수로 null을 사용하여이 메소드를 호출 할 수 있습니다. 그러나 이것은 꽤 어리석은 연습입니다. 왜 지구상에서 그렇게하고 싶습니까?
dqhendricks

2
구체적인 예 : function addView($name, Template $template, SecurityMode $securityMode = null, $methodName = null);당신은 $methodName있지만 없을 수 있습니다 $securityMode.
Nicole

7

인터페이스를 사용하면 개방 폐쇄 원칙을 구현하고 느슨하게 결합 된 코드 기반을 유지하며 최고의 OOP 디자인 패턴을 구현할 수 있습니다.

예를 들어, 한 클래스가 다른 클래스를 인수로 허용하는 경우 :

class A {

    public function __construct(B $class_b) {
        // use class b
        $class_b->run();
    }
}

클래스 A와 클래스 B는 이제 밀접한 결합을 가지며 클래스 A는 B를 제외한 다른 클래스를 사용할 수 없습니다. 유형 힌트는 올바른 유형의 인수를 갖지만 이제 A와 B 사이의 관계를 강화했습니다.

그러나 클래스 A가 run () 메소드를 가진 모든 유형의 클래스를 사용할 수 있기를 원한다고 가정 해 봅시다. 이것은 기본적으로 COMMAND 디자인 패턴입니다. 해결하려면 콘크리트 클래스 대신 인터페이스를 사용하여 힌트를 입력하십시오. B는 해당 인터페이스를 구현하고 클래스 A의 인수로 허용됩니다.이 방법으로 클래스 A는 해당 인터페이스를 생성자에 대한 인수로 사용하는 모든 클래스를 승인 할 수 있습니다.

이 유형의 코딩은 대부분의 OOP 디자인 패턴에 사용되며 나중에 더 쉽게 코드를 변경할 수 있습니다. 이들은 AGILE 프로그래밍의 기본 사항 중 일부입니다.


1
또는 B의 하위 클래스
Mez

7

@pjskeptic에는 좋은 대답 이 있으며 @Kamil Tomšík는 그 대답에 대해 좋은 의견을 가지고 있습니다.

PHP와 같이 동적으로 유형이 지정된 언어의 가장 큰 장점은 객체에 메소드를 사용하려고 시도 할 수 있으며 메소드가 없으면 소리 지르지 않는다는 것입니다.

PHP와 같이 동적으로 유형이 지정된 언어의 문제는 객체에서 메소드를 사용하려고 시도 할 수 있으며 메소드가 없을 때 소리를 지르는 것입니다.

인터페이스는 알 수없는 객체에서 메소드를 호출하고 메소드가 있는지 확인하는 편리한 방법을 추가합니다 (정확히 작동하거나 작동하지는 않음). 언어의 필수 부분은 아니지만 코딩이 더 편리합니다. 강력하게 형식화 된 OOP 개발자는 강력하게 형식화 된 PHP 코드를 작성하여 다른 PHP 개발자가 작성한 느슨하게 형식화 된 PHP 코드와 함께 작동 할 수 있습니다.

다음과 같은 기능 :

foo( IBar $bar )
{
  $baz = $bar->baz();
  ...
}

보다 편리합니다 :

foo( $bar )
{
  if ( method_exists( $bar, 'baz' ) )
  {
    $baz = $bar->baz();
  }
  else
  {
    throw new Exception('OMGWTF NO BAZ IN BAR!');
  }
  ...
}

IMHO 간단하고 읽기 쉬운 코드가 더 나은 코드입니다.


1
대신 누군가가 잘못된 데이터로 함수를 호출 할 때 메소드를 확인하지 않고 충돌하고 타는 것입니다. 누군가가 당신의 기능을 잘못 사용하면 문제가되지 않습니다.
Raynos

정확하지 않음-프록시, 어댑터, 데코레이터 등과 같이 역동적 인 "오리"를 전달하려는 사람에게는 악몽이 있습니다.
Kamil Tomšík

1
@ 카밀? 어떻게 요? 프록시는이 함수와 함께 사용할 수 있도록 인터페이스를 구현하지 않는 무언가에 대한 래퍼 클래스입니다.
tylermac

__tyler ()를 사용하는 @tylermac 동적 프록시-__call이 유일한 방법 인 경우, 단순히 IBar를 구현할 수 없으므로 foo (IBar $ bar)에 전달할 수 없습니다.
Kamil Tomšík

5

오리 타이 퍼 인 경우 완전히 쓸모가 없습니다. 실제로 오리 타이핑을 할 때 모든 유형 힌트를 사용하는 라이브러리 / 프레임 워크로 작업하는 것은 꽤 성가신 일입니다.

이는 모든 종류의 동적 메타 프로그래밍 (마법 방법)에도 적용됩니다.


3

PHP는 하지 느슨하거나 강하게,하지만 동적으로 입력 .

인터페이스에 대해 가장 먼저 알아야 할 것은 인터페이스의 장점이 무엇입니까?

OOP에서 인터페이스는 유형뿐만 아니라 동작에 관한 것입니다.

PHP에는 또한 유형 힌트 기능 이 있으므로 Java와 같은 순수한 oo 언어에서와 마찬가지로 인터페이스를 사용할 수 있습니다.

interface File
{
    public function getLines();
}

CSVFile implements File
{
    public function getLines()
    {}
}

XMLFile implements File 
{
    public function getLines()
    {}
}

JSONFile implements File 
{
    public function getLines()
    {}
}

class FileReader
{
    public function read(File $file)
    {
        foreach($file->getLines() as $line)
        {
            // do something
        }
    }
}

PHP 인터페이스 구현을 사용하면 PHPUnit을 사용하여 추상 클래스에 대한 모의 객체를 만들 수도 있습니다. 이것은 기능의 지옥입니다.

public function testSomething()
{
    $mock = $this->getMockForAbstractClass('File');

    $mock->expects($this->once())
         ->method('getLines')
         ->will($this->returnValue(array()));

    // do your assertions
}

따라서 기본적으로 언어 기능 (인터페이스 중 하나)을 사용하여 PHP에서 SOLID 호환 응용 프로그램 을 사용할 수 있습니다 .


0

인터페이스는 콘크리트보다 의존성 주입에 훨씬 유용합니다. 베어 본 예제로 :

interface Istore { 
  public function save(); 
}

class Article_DB implements Istore 
{ 
  public function save($data) 
  {
    // do save to format needed.
  } 
}

class Article
{
   private $content;

   public function content($content)
   {
     $this->content = $content;
   }

   public function save(Istore $store)
   {
     $store->save($this->content);
   }
}

$article = new Article();
$article->content('Some content');

$store = new Article_DB();
$article->save($store);

이제 필요가 바뀌고 PDF로 저장하고 싶다고 말하십시오. Article 클래스를 오염시키는 대신 해당 목적을 위해 새로운 클래스를 만들 수 있습니다.

class Article_PDF implements Istore 
{ 
  public function save($data) 
  {
    // do save to format needed.
  } 
}


$article = new Article();
$article->content('Some content');

$store = new Article_PDF();
$article->save($store);

Article 클래스에는 이제 저장하기 위해 사용하는 클래스가 Istore 인터페이스를 구현해야하는 계약이 있습니다. 저장 위치 또는 저장 방법은 중요하지 않습니다.


-1

인터페이스를 구현하는 "가짜"실제 객체를 제공 할 수 있습니다. 그런 다음 실제 서버, 파일 시스템, 소켓, 데이터베이스 등을 요구하지 않고 코드의 일부를 단위 테스트 할 수 있습니다.


-3

많은 사람들이 아마 이런 식으로 대답하는 것을 싫어할 것입니다. 그러나 타이핑 문제에 대한 해결책은 PHP로 쉽게 고칠 수 있습니다. 그렇습니다. PHP는 느슨하게 입력되었으므로 기본적으로 유형이 가정됩니다. 이는 특히 대부분의 사람들이 다루는 비교 작업에서 일부 문제를 일으킬 있습니다. 즉, PHP는 사용중인 것을 원하는 유형으로 캐스팅 한 다음 비트 비교 연산자를 사용하면 강력한 유형의 언어만큼 엄격 할 수 있습니다. 다음은 내가 말하는 것을 생각할 수있는 가장 쉬운 예입니다.

$ myVar = (int) 0; $ myOtherVar = '0';

($ myVar == $ myVar)를 비교하면 (bool) true가됩니다.

그러나 ($ myVar === $ myVar)를 비교하는 것은 "typed"비교와 마찬가지로 (bool) false입니다.

PHP의 작동 방식에 문제가있는 경우, 개발자가 Java로 프로그램을 진행하고 라이브로 보내거나 원하는 방식으로 사용하는 방식에 문제가있는 경우 개발자가이 점에 대해 논쟁하지 않기를 바랍니다. 어쨌든 그것에 대해 암캐가 당신에게 어떤 유익을 줍니까? 하루 종일 조롱 할 핑계가 있습니까? 당신은 다른 사람보다 더 좋아 보이나요? 글쎄, 당신이 다른 사람을 나쁘게 보이게 할 의사가 있기 때문에 자신에 대해 너무 높게 느끼는 것이 좋지만 실제로는 그것이 당신의 취향이며 다른 사람에 대한 당신의 믿음을 강요하면 실제로 세 가지 일을 일으키기가 쉽지 않은 방식으로 코드를 작성합니다.

1) 그들은 당신의 방식으로 코딩하지만 표준에 따라 "더러운"것입니다 (생각해보십시오, 자바 프로그래머가 첫 번째 PHP 프로그램을 만들거나 그 반대의 방법을 보았습니까? 아니면 방법론을 변경하는 것과 같은 방법이거나 심지어 더 나쁠 수도 있습니다).

2) 다른 소리를 낼 것입니다

3) 생산하는데 시간이 더 걸릴 것이다. 어쩌면 단기간에 더 좋아 보일 수도 있지만 팀 전체가 더 나빠 보일 것입니다 (다른 사람보다 느리게 코딩 할 수 있으며 팀이 합리적인 시간 내에 결과물을 만나는 한 반드시 나쁘지는 않습니다. 그러나 일반적으로 조금 더 빨리 수행 한 사람에게 습관을 강요하면 전체 팀이 느려지 게되어 매우 까다로운 워크 플로에서 더 나빠 보일 수 있습니다.)

개인적으로 OOP를 사용하여 전체 프로그램을 몇 가지 다른 언어로 작성할 수는 있지만 절차 적 PHP 코드 작성을 선호합니다. 즉, 나는 좋은 OOP 코드와 나쁜 OOP 코드, 좋은 절차 적 코드와 나쁜 절차 적 코드를 보았습니다 ... 실제와는 관련이 없지만 사용하는 습관 과 관련이 있습니다. 많은 것들이 제 해석 적 감정입니다 ... 그것은 그 개발자들에 대해 나쁜 말을하거나 "나의 방법은 최고"BS와 자랑한다고 말하려는 것이 아닙니다. 그것은 저에게 딱 맞습니다. 내 작업에 만족하고 자랑스럽게 생각합니다. 표준을 설정해야하는 이유가 있지만 선택한 표준에 포함하는 것이 매우 중요합니다. 내 가슴에서 빼앗아 주셔서 감사합니다. 좋은 하루 보내세요


-4
  1. 인터페이스는 OOP 패러다임의 일부입니다. 따라서 객체 지향 부품이나 시스템을 만들 때 많은 경우에 매우 유용합니다.
  2. 그래서. 왜 안돼? ;-)

예 : 데이터를 캐시해야합니다. 어떻게? 캐싱을위한 많은 다른 엔진이 있는데, 어느 엔진이 가장 좋습니까? key, get, put, clear 등과 같은 일련의 메소드가있는 ICacheDriver 인터페이스가있는 추상 레이어가 있는지 궁금합니다. 현재 프로젝트에 필요한 것을 구현하고 필요할 때 변경하십시오. 또는 toString의 간단한 사용법. 표시 가능한 다른 개체 집합이 있습니다. Stringable 인터페이스를 구현하고 (toString 메소드를 설명 함 [PHP에는 실제로 이와 같은 인터페이스는 없지만]) 모든 객체를 (string) $ obj로 인터페이싱합니다. switch (true) 대신해야 할 모든 것이 있습니다. {case $ obj isntanceof A1 : "do 1"; 단절; ...}

단순한. "왜?"라는 질문은 없습니다. "그것을 더 잘 사용하는 방법"이 있습니다. ;-) 행운을 빕니다.


-5

내 추측.

PHP는 많은 초급 프로그래머 가 사용하며 초급 프로그래머는 대학에서 Java배웁니다 .

프로그래밍 101 과정을 마치고 젠드에게 잔소리하기 시작합니다. 자바 기능을 원하기 때문입니다. 왜냐하면 그들이 생각하는 방식이기 때문입니다. 자신의 용어에 대한 생각 (또는 오리 타이핑 이해)은 20 세일 때 어렵습니다.

젠드는 그것의, 실용적이며 기능 추가하는 것이 더 쉽습니다 곳 옳았들은 척하는 것보다 다른.
또한 사용자 를 떠나지 않고 더 많은 사용자 를 구매 하므로 좋을 것입니다.

이 과정의 또 다른 사례? .NET 및 Java 과정을 처음 접하는 사람들 또한 Foundation 클래스의 프레임 워크를 원합니다 . Zend가 Zend 프레임 워크를 싹 트울 때까지 계속 진행합니다 . 이것은 더 많은 사용자를 구매합니다. 그리고 계속해서 ...

( 수년 동안 PHP 팀이 고생 한 것으로 알려진 유일한 언어 기능은 입니다 goto)


내 비전에는 PHP12아마도 기능 및 데이터 유형 패러다임에 대한 윙크와 함께 세계의 모든 구문 기능이있을 것입니다 goto.
ZJR

"만약 20 살 때 힘들다"나이가 어떻게 그런 개념을 이해하는 것과 관련이있을 수 있을까?
Evicatos

@Evicatos 고등학생은 일종의 프로그램이지만 보통 교사가 적고 이름 지정 규칙이 열악하며 유지 관리 할 수없는 얼룩을 생성합니다. 그들은 대학을 시작하는 동안 바로 프로그래밍하는 법을 배우고 , 그것을 시작하는 데 몇 년이 걸립니다. 그런 다음 첫 해에 배운 어려운 유형의 업계에서 인정하고 엄숙하게 찬성 한 언어에서 벗어나기 시작하여보다 실용적이고 오리 언어 인 언어로 바뀝니다. 나는 이것이 많은 프로그래머들이 공유하는 부시도라고 생각합니다. 다시 말하지만, 이것은 당신의 경험을 반영하지 않을 수도 있습니다. 그렇다면 길을 알려주십시오.
ZJR
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.