문제

인터페이스 이를 구현하는 클래스의 메서드를 정의하는 코드를 생성할 수 있습니다.그러나 해당 메서드에 코드를 추가할 수는 없습니다.

추상 수업 메소드에 코드를 추가하는 동시에 동일한 작업을 수행할 수 있습니다.

이제 추상 클래스를 사용하여 동일한 목표를 달성할 수 있다면 왜 인터페이스 개념이 필요한가요?

나는 이것이 C++에서 Java까지의 OO 이론과 관련이 있다는 말을 들었습니다. 이는 PHP의 OO 항목이 기반으로 하는 것입니다.이 개념은 Java에서는 유용하지만 PHP에서는 유용하지 않습니까?추상 클래스에 자리 표시자가 흩어지는 것을 방지하는 방법일까요?뭔가 빠졌나요?

도움이 되었습니까?

해결책

인터페이스의 전체 요점은 클래스가 여러 인터페이스를 구현하도록 강제할 수 있지만 여전히 다중 상속을 허용하지 않는 유연성을 제공하는 것입니다.여러 클래스에서 상속할 때 발생하는 문제는 많고 다양하며 위키피디아 그 페이지에는 그것들이 꽤 잘 요약되어 있습니다.

인터페이스는 절충안입니다.다중 상속과 관련된 대부분의 문제는 추상 기본 클래스에 적용되지 않으므로 요즘 대부분의 현대 언어는 다중 상속을 비활성화하면서도 추상 기본 클래스 인터페이스를 호출하고 클래스가 원하는 만큼 이를 "구현"할 수 있도록 허용합니다.

다른 팁

이 개념은 객체 지향 프로그래밍 전반에 걸쳐 유용합니다.나에게 있어서 나는 인터페이스를 계약으로 생각한다.내 학급과 여러분의 학급이 이 메서드 서명 계약에 동의하면 "인터페이스"할 수 있습니다.추상 클래스의 경우 일부 메서드를 제거하는 기본 클래스에 더 가깝다고 생각하며 세부 사항을 입력해야 합니다.

이미 추상 클래스가 있는데 왜 인터페이스가 필요합니까?다중 상속을 방지합니다(알려진 여러 문제가 발생할 수 있음).

그러한 문제 중 하나는 다음과 같습니다.

"다이아몬드 문제"(때로는 "치명적인 죽음의 다이아몬드"라고도 함)는 두 클래스 B와 C에서 A와 클래스 D가 B와 C에서 상속 될 때 발생하는 모호성입니다.a에 b와 c가 재정의 된 메소드가 있고 d는 그것을 재정의하지 않으면 어떤 버전의 메소드가 d 상속을하는지B의 것인가요, 아니면 C의 것인가요?

원천: https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem

인터페이스를 사용하는 이유/언제?예를 들어 ...세상의 모든 자동차는 동일한 인터페이스(메서드)를 가지고 있습니다.. AccelerationPedalIsOnTheRight(), BrakePedalISOnTheLeft().각 자동차 브랜드가 다른 브랜드와 다른 "방법"을 가지고 있다고 상상해 보십시오.BMW는 오른쪽에 브레이크가 있고, 혼다는 휠 왼쪽에 브레이크가 있습니다.사람들은 다른 브랜드의 자동차를 구입할 때마다 이러한 "방법"이 어떻게 작동하는지 배워야 합니다.그렇기 때문에 여러 "장소"에서 동일한 인터페이스를 사용하는 것이 좋습니다.

인터페이스가 당신에게 어떤 역할을 합니까(누군가가 인터페이스를 사용하는 이유는 무엇입니까)?인터페이스는 "실수"를 방지합니다(특정 인터페이스를 구현하는 모든 클래스가 인터페이스에 있는 메서드를 모두 갖게 됨을 보장합니다).

// Methods inside this interface must be implemented in all classes which implement this interface.
interface IPersonService
{   
    public function Create($personObject);
}

class MySqlPerson implements IPersonService
{
    public function Create($personObject)
    {
        // Create a new person in MySql database.
    }
}

class MongoPerson implements IPersonService
{
    public function Create($personObject)
    {
        // Mongo database creates a new person differently then MySQL does. But the code outside of this method doesn't care how a person will be added to the database, all it has to know is that the method Create() has 1 parameter (the person object).
    }
}

이 방법으로, Create() 메소드는 항상 같은 방식으로 사용됩니다.우리가 사용하고 있는지는 중요하지 않습니다. MySqlPerson 수업이나 MongoPerson 수업.메소드를 사용하는 방식은 동일하게 유지됩니다(인터페이스도 동일하게 유지됨).

예를 들어, 다음과 같이 사용됩니다(코드의 모든 곳에서).

new MySqlPerson()->Create($personObject);
new MongoPerson()->Create($personObject);

이렇게 하면 다음과 같은 일이 일어날 수 없습니다.

new MySqlPerson()->Create($personObject)
new MongoPerson()->Create($personsName, $personsAge);

여러 인터페이스를 사용하는 것보다 하나의 인터페이스를 기억하고 어디서나 동일한 인터페이스를 사용하는 것이 훨씬 쉽습니다.

이렇게 해서 내부에는 Create() 메서드는 이 메서드를 호출하는 "외부" 코드에 영향을 주지 않고 클래스마다 다를 수 있습니다.외부 코드가 알아야 할 모든 것은 메소드가 Create() 매개변수가 1개 있습니다($personObject), 외부 코드가 메소드를 사용/호출하는 방식이기 때문입니다.외부 코드는 메서드 내부에서 무슨 일이 일어나고 있는지 신경 쓰지 않습니다.단지 그것을 사용/호출하는 방법만 알아야 합니다.

인터페이스 없이도 이 작업을 수행할 수 있지만 인터페이스를 사용하면 "더 안전"합니다(실수를 방지하기 때문입니다).인터페이스는 메소드가 다음을 보장합니다. Create() 인터페이스를 구현하는 모든 클래스에서 동일한 시그니처(동일한 유형 및 동일한 수의 매개변수)를 갖습니다.이렇게 하면 다음을 구현하는 모든 클래스가 있는지 확인할 수 있습니다. IPersonService 인터페이스에는 메소드가 있습니다 Create() (이 예에서는) 매개변수가 1개만 필요합니다($personObject) 호출/사용됩니다.

인터페이스를 구현하는 클래스는 인터페이스가 갖고 있는 모든 메소드를 구현해야 합니다.

나는 내 자신을 너무 많이 반복하지 않기를 바랍니다.

인터페이스와 추상 클래스 사용의 차이점은 언어 자체에 의한 시행보다는 코드 구성과 더 관련이 있습니다.나는 다른 개발자들이 의도한 디자인 패턴 내에서 작업할 수 있도록 코드를 준비할 때 이를 많이 사용합니다.인터페이스는 귀하의 코드가 귀하가 액세스할 수 없는 코드에서 발생할 수 있는 미리 정의된 API 호출 세트에 응답하는 데 동의하는 일종의 "계약에 의한 설계"입니다.

추상 클래스로부터의 상속은 "is a" 관계이지만 항상 원하는 것은 아니며 인터페이스 구현은 "a처럼 작동하는" 관계에 가깝습니다.이 차이는 특정 상황에서는 상당히 중요할 수 있습니다.

예를 들어, 다른 많은 클래스(계정 유형 등)가 확장되는 추상 클래스 Account가 있다고 가정해 보겠습니다.해당 유형 그룹에만 적용할 수 있는 특정 메소드 세트가 있습니다.그러나 이러한 계정 하위 클래스 중 일부는 Versionable, Listable 또는 Editable을 구현하여 해당 API를 사용할 것으로 예상되는 컨트롤러에 포함될 수 있습니다.컨트롤러는 그것이 어떤 유형의 객체인지 상관하지 않습니다.

대조적으로, Account에서 확장되지 않는 객체(예: User 추상 클래스)를 생성할 수도 있고 여전히 Listable 및 Editable을 구현할 수 있지만 Versionable은 구현할 수 없습니다. 이는 여기서는 의미가 없습니다.

이런 식으로 FooUser 하위 클래스는 계정이 아니지만 편집 가능한 객체처럼 작동한다는 의미입니다.마찬가지로 BarAccount는 Account에서 확장되지만 User 하위 클래스는 아니지만 Editable, Listable 및 Versionable을 구현합니다.

편집 가능, 나열 가능 및 버전 가능을 위한 이러한 모든 API를 추상 클래스 자체에 추가하는 것은 복잡하고 추악할 뿐만 아니라 Account 및 User의 공통 인터페이스를 복제하거나 내 User 객체가 Versionable을 구현하도록 강제합니다. 예외.

인터페이스는 본질적으로 여러분이 만들 수 있는 것에 대한 청사진입니다.그들은 클래스가 어떤 메소드를 정의하는지 정의합니다. 가지고 있어야 한다, 그러나 이러한 제한 사항을 벗어나는 추가 메서드를 만들 수 있습니다.

메소드에 코드를 추가할 수 없다는 것이 무슨 뜻인지 잘 모르겠습니다. 왜냐하면 가능하기 때문입니다.인터페이스를 추상 클래스에 적용하고 있습니까, 아니면 이를 확장하는 클래스에 적용하고 있습니까?

추상 클래스에 적용된 인터페이스의 메서드는 해당 추상 클래스에서 구현되어야 합니다.그러나 해당 인터페이스를 확장 클래스에 적용하면 메서드는 확장 클래스에서만 구현하면 됩니다.여기서는 틀릴 수도 있습니다. 저는 인터페이스를 가능한 한 자주 사용하지 않습니다.

저는 항상 인터페이스를 외부 개발자를 위한 패턴이나 모든 것이 올바른지 확인하기 위한 추가 규칙 세트로 생각했습니다.

PHP에서 인터페이스를 사용합니다:

  1. 구현을 숨기려면 - 객체 클래스에 대한 액세스 프로토콜을 설정하고 해당 객체를 사용한 모든 위치에서 리팩토링하지 않고 기본 구현을 변경합니다.
  2. 유형을 확인하려면 - 매개변수에 특정 유형이 있는지 확인하는 것과 같습니다. $object instanceof MyInterface
  3. 런타임에 매개변수 검사를 시행하려면
  4. 단일 클래스에 여러 동작을 구현하려면(복잡한 유형 구축)

    Car 클래스는 EngineInterface, BodyInterface, SteeringInterface를 구현합니다.

그래서 Car 지금 개체 ca start(), stop() (엔진 인터페이스) 또는 goRight(),goLeft() (스티어링 인터페이스)

그리고 지금은 생각할 수 없는 다른 것들도 있어요

4번은 추상 클래스로는 처리할 수 없는 가장 확실한 사용 사례일 것입니다.

Java로 생각하기:

인터페이스는“이것은이 특정 인터페이스를 구현하는 모든 클래스의 모습입니다.”라고 말합니다. 따라서 특정 인터페이스를 사용하는 모든 코드는 해당 인터페이스를 위해 어떤 메소드를 호출 할 수 있는지 알고 있으며 그게 전부입니다.따라서 인터페이스는 클래스 간 "프로토콜"을 설정하는 데 사용됩니다.

인터페이스는 클래스를 확장할 수 있는 기반이 아니라 필요한 기능의 맵으로 존재합니다.

다음은 추상 클래스가 맞지 않는 인터페이스를 사용하는 예입니다.
사용자가 외부 소스에서 캘린더 데이터를 가져올 수 있는 캘린더 애플리케이션이 있다고 가정해 보겠습니다.각 유형의 데이터 소스(ical, rss,atom,json) 가져오기를 처리하는 클래스를 작성합니다. 이러한 각 클래스는 내 애플리케이션이 데이터를 가져오는 데 필요한 공통 공용 메소드를 모두 갖도록 하는 공통 인터페이스를 구현합니다.

<?php

interface ImportableFeed 
{
    public function getEvents();
}

그런 다음 사용자가 새 피드를 추가하면 피드 유형을 식별하고 해당 유형용으로 개발된 클래스를 사용하여 데이터를 가져올 수 있습니다.특정 피드에 대한 데이터를 가져오기 위해 작성된 각 클래스는 완전히 다른 코드를 갖게 됩니다. 그렇지 않으면 내 애플리케이션에서 해당 클래스를 사용할 수 있도록 하는 인터페이스를 구현하는 데 필요하다는 사실을 제외하면 클래스 간에 유사점이 거의 없을 수 있습니다.추상 클래스를 사용한다면 getEvents() 메서드를 재정의하지 않았으므로 이 인스턴스에서 애플리케이션이 중단된다는 사실을 매우 쉽게 무시할 수 있습니다. 반면 인터페이스를 사용하면 메서드 중 하나라도 실행되지 않으면 앱이 실행되지 않습니다. 인터페이스에 정의된 내용은 이를 구현한 클래스에 존재하지 않습니다.내 앱은 피드에서 데이터를 가져오는 데 어떤 클래스를 사용하는지 신경 쓸 필요가 없으며 해당 데이터를 가져오는 데 필요한 메서드만 존재하면 됩니다.

한 단계 더 나아가 다른 피드 유형을 추가하려는 의도로 캘린더 앱으로 돌아올 때 인터페이스가 매우 유용하다는 것이 입증되었습니다.ImportableFeed 인터페이스를 사용한다는 것은 이 인터페이스를 구현하는 새 클래스를 추가하기만 하면 다양한 피드 유형을 가져오는 더 많은 클래스를 계속 추가할 수 있음을 의미합니다.이를 통해 내 핵심 애플리케이션은 새 피드 가져오기 클래스가 ImportableFeed 인터페이스를 구현하는 한 인터페이스에 필요한 사용 가능한 공개 메서드만 의존하기 때문에 핵심 애플리케이션에 불필요하게 많은 양을 추가하지 않고도 수많은 기능을 추가할 수 있습니다. 그냥 제자리에 놓고 계속 움직일 수 있다는 걸 알아요.

이것은 아주 간단한 시작일 뿐입니다.그런 다음 클래스가 처리하는 피드 유형과 관련된 더 많은 기능을 제공하는 구현에 필요한 모든 캘린더 클래스가 있는 또 다른 인터페이스를 만들 수 있습니다.또 다른 좋은 예는 피드 유형 등을 확인하는 방법입니다.

이는 질문 이상의 내용이지만 위의 예를 사용했기 때문에 다음과 같습니다.이러한 방식으로 사용되는 경우 인터페이스에는 고유한 문제가 발생합니다.인터페이스와 일치하도록 구현된 메서드에서 반환되는 출력을 확인해야 하며 이를 달성하기 위해 PHPDoc 블록을 읽고 반환 유형을 인터페이스의 PHPDoc 블록에 유형 힌트로 추가하는 IDE를 사용합니다. 이를 구현하는 구체적인 클래스로 변환합니다.이 인터페이스를 구현하는 클래스의 데이터 출력을 사용하는 내 클래스는 최소한 이 예제에서 반환된 배열을 예상한다는 것을 알게 됩니다.

<?php
interface ImportableFeed 
{
    /**
     * @return array
     */
    public function getEvents();
}

추상 클래스와 인터페이스를 비교할 여지가 많지 않습니다.인터페이스는 구현 시 클래스에 공용 인터페이스 세트가 있어야 하는 단순한 맵입니다.

인터페이스는 단지 개발자가 특정 메서드를 구현하도록 하기 위한 것이 아닙니다.아이디어는 이러한 클래스에 특정 메서드가 있다는 것이 보장되기 때문에 클래스의 실제 유형을 모르더라도 이러한 메서드를 사용할 수 있다는 것입니다.예:

interface Readable {
  String read();
}

List<Readable> readables; // dunno what these actually are, but we know they have read();
for(Readable reader : readables)
  System.out.println(reader.read());

많은 경우 추상 여부에 관계없이 기본 클래스를 제공하는 것은 의미가 없습니다. 구현이 크게 다양하고 몇 가지 메서드 외에 공통점을 공유하지 않기 때문입니다.

동적 유형 언어에는 인터페이스가 필요하지 않은 "오리 유형 지정"이라는 개념이 있습니다.개체에 호출하는 메서드가 있다고 자유롭게 가정할 수 있습니다.이는 개체에 일부 메서드(예: read())가 있지만 인터페이스를 구현하지 않는 정적으로 유형이 지정된 언어의 문제를 해결합니다.

내 생각에는, 함수형이 아닌 추상 클래스보다 인터페이스가 더 선호되어야 한다고 생각합니다.두 개를 구문 분석하여 결합하는 대신 인스턴스화된 개체가 하나만 있기 때문에 성능 저하가 발생하더라도 놀라지 않을 것입니다(확실하지는 않지만 내부 작동에 익숙하지 않습니다). OOP PHP).

인터페이스가 Java에 비해 유용성/의미가 떨어지는 것은 사실입니다.반면, PHP6에서는 반환 값에 대한 유형 힌트를 포함하여 훨씬 더 많은 유형 힌트를 도입합니다.이는 PHP 인터페이스에 일부 가치를 추가해야 합니다.

tl;dr:인터페이스는 따라야 할 메소드 목록(API를 생각해 보세요)을 정의하는 반면, 추상 클래스는 일부 기본/공통 기능을 제공하며, 하위 클래스는 특정 요구 사항에 맞게 이를 구체화합니다.

이 점에서 PHP가 다른지 기억이 나지 않지만 Java에서는 여러 인터페이스를 구현할 수 있지만 여러 추상 클래스를 상속할 수는 없습니다.나는 PHP가 같은 방식으로 작동한다고 가정합니다.

PHP에서는 쉼표로 구분하여 여러 인터페이스를 적용할 수 있습니다. (제 생각엔 깔끔한 솔루션은 아닌 것 같습니다.)

여러 추상 클래스의 경우 서로 확장되는 여러 추상을 가질 수 있습니다(다시 말하지만 이에 대해 완전히 확신할 수는 없지만 이전에 어딘가에서 본 것 같습니다).확장할 수 없는 유일한 것은 최종 클래스입니다.

인터페이스는 코드에 성능 향상이나 그와 유사한 것을 제공하지 않지만 유지 관리가 가능하도록 만드는 데 큰 도움이 될 수 있습니다.추상 클래스(또는 비추상 클래스)를 사용하여 코드에 대한 인터페이스를 설정할 수 있다는 것은 사실이지만 적절한 인터페이스(키워드로 정의하고 메서드 시그니처만 포함하는 인터페이스)는 훨씬 더 쉽습니다. 정리해서 읽어보세요.

즉, 나는 클래스보다 인터페이스를 사용할지 여부를 결정할 때 재량권을 사용하는 경향이 있습니다.때로는 기본 메서드 구현이나 모든 하위 클래스에 공통되는 변수가 필요합니다.

물론 다중 인터페이스 구현에 대한 요점도 건전한 것입니다.여러 인터페이스를 구현하는 클래스가 있는 경우 해당 클래스의 개체를 동일한 애플리케이션에서 다른 유형으로 사용할 수 있습니다.

하지만 귀하의 질문이 PHP에 관한 것이라는 사실이 상황을 좀 더 흥미롭게 만듭니다.인터페이스에 입력하는 것은 여전히 ​​PHP에서 엄청나게 필요한 것은 아닙니다. PHP에서는 유형에 관계없이 모든 메소드에 무엇이든 입력할 수 있습니다.메소드 매개변수를 정적으로 입력할 수 있지만 그 중 일부가 손상되었습니다(문자열은 약간의 딸꾹질을 유발한다고 생각합니다).대부분의 다른 참조를 입력할 수 없다는 사실과 결합하여 PHP에서 정적 입력을 강제하는 것은 별로 가치가 없습니다(이 지점에서).그렇기 때문에 인터페이스의 가치는 PHP로, 이 지점에서 더 강력한 형식의 언어보다 훨씬 적습니다.가독성이라는 이점이 있지만 그 외에는 거의 없습니다.다중 구현은 여전히 ​​메소드를 선언하고 구현자 내에서 본문을 제공해야 하기 때문에 유익하지도 않습니다.

인터페이스는 유전자와 같습니다.

추상 수업은 실제 부모와 같습니다.

이들의 목적은 유전적이지만 추상 클래스와 인터페이스의 경우 상속되는 것이 더 구체적입니다.

다음은 PHP 인터페이스에 대한 포인트입니다

  1. 이는 클래스에서 필수 메소드 수를 정의하는 데 사용됩니다. [html을 로드하려면 ID와 이름이 필요하므로 이 경우 인터페이스에는 setID 및 setName이 포함됩니다].
  2. 인터페이스는 클래스가 클래스에 정의된 모든 메서드를 포함하도록 엄격하게 강제합니다.
  3. 공개 접근성이 있는 인터페이스에서만 메서드를 정의할 수 있습니다.
  4. 클래스와 같은 인터페이스를 확장할 수도 있습니다.확장 키워드를 사용하여 PHP에서 인터페이스를 확장할 수 있습니다.
  5. 다중 인터페이스를 확장합니다.
  6. 두 인터페이스가 동일한 이름으로 기능을 공유하는 경우 두 인터페이스를 구현할 수 없습니다.오류가 발생합니다.

예제 코드:

interface test{
    public function A($i);
    public function B($j = 20);
}

class xyz implements test{
    public function A($a){
        echo "CLASS A Value is ".$a;
    }
    public function B($b){
        echo "CLASS B Value is ".$b;
    }
}
$x = new xyz();
echo $x->A(11);
echo "<br/>";
echo $x->B(10);

우리는 추상 클래스와 인터페이스가 하위 클래스에서 구현되어야 하는 추상 메서드를 제공한다는 점에서 유사하다는 것을 확인했습니다.그러나 여전히 다음과 같은 차이점이 있습니다.

1.인터페이스에는 추상 메서드와 상수가 포함될 수 있지만 구체적인 메서드와 변수는 포함될 수 없습니다.

2. 인터페이스의 모든 메소드는 공공의 가시성 범위.

3. 클래스는 둘 이상의 인터페이스를 구현할 수 있지만 하나의 추상 클래스에서만 상속 될 수 있습니다.

                                  interface                      abstract class
the code                     - abstract methods               - abstract methods
                             - constants                      - constants                  
                                                              - concrete methods
                                                              - concrete variables

access modifiers             
                             - public                         - public
                                                              - protected
                                                              - private
                                                                etc.
number of parents          The same class can implement
                           more than 1 interface              The child class can 
                                                              inherit only from 1 abstract class

이것이 누구에게나 이해하는 데 도움이 되기를 바랍니다!

다른 언어에 대해서는 잘 모르지만 그곳의 인터페이스 개념은 무엇입니까?하지만 PHP에 대해서는 최선을 다해 설명하겠습니다.인내심을 갖고 도움이 되셨다면 댓글을 남겨주세요.

인터페이스는 하위 클래스 집합이 수행하는 작업을 지정하지만 수행 방법은 지정하지 않는 "계약"으로 작동합니다.

규칙

  1. 인터페이스는 인스턴스화할 수 없습니다.

  2. 인터페이스에서는 어떤 메소드도 구현할 수 없습니다.여기에는 메서드의 .signature만 포함되어 있고 세부 정보(본문)는 포함되어 있지 않습니다.

  3. 인터페이스에는 메서드 및/또는 상수가 포함될 수 있지만 속성은 포함될 수 없습니다.인터페이스 상수에는 클래스 상수와 동일한 제한 사항이 있습니다.인터페이스 메서드는 암시적으로 추상적입니다.

  4. 인터페이스는 생성자 나 소멸자를 선언해서는 안됩니다. 이는 클래스 수준의 구현 세부 사항이므로.
  5. 인터페이스의 모든 메서드는 공개적으로 표시되어야 합니다.

이제 예를 들어 보겠습니다.두 개의 장난감이 있다고 가정해 보겠습니다.하나는 개이고 다른 하나는 고양이입니다.

우리가 알고 있듯이 개는 짖고 고양이는 야옹거립니다. 이 두 가지의 말하는 방법은 동일하지만 기능이나 구현이 다릅니다.사용자에게 말하기 버튼이 있는 리모콘을 제공한다고 가정해 보겠습니다.

사용자가 말하기 버튼을 누르면 장난감은 개든 고양이든 상관없이 말해야 합니다.

구현이 다르기 때문에 추상 클래스가 아닌 인터페이스를 사용하는 것이 좋은 경우입니다.왜?기억하다

추상이 아닌 메소드를 추가하여 하위 클래스를 지원해야 하는 경우 추상 클래스를 사용해야 합니다.그렇지 않으면 인터페이스를 선택하게 됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top