인터페이스코드를 구현하는 클래스의 메서드를 정의하는 코드를 만들 수 있습니다. 그러나 이러한 메소드에 코드를 추가 할 수는 없습니다.
추상 수업메서드에 코드를 추가하는 것과 함께 동일한 작업을 수행 할 수 있습니다.
이제 추상 클래스를 사용하여 동일한 목표를 달성 할 수 있다면 인터페이스의 개념이 필요한 이유는 무엇입니까?
나는 OO 이론을 C ++에서 Java에 이르기까지해야한다는 말을 들었다. 이것은 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()
(이 예에서는) 하나의 매개 변수 만 필요합니다 ($personObject
) 호출 / 사용 얻을.
인터페이스를 구현하는 클래스는 인터페이스가 수행하는 모든 메소드를 구현해야합니다.
나는 내가 너무 많이 반복하지 않기를 바란다.
인터페이스와 추상 클래스를 사용하는 것의 차이는 언어 자체에 의한 시행보다 나에게 코드 구성과 관련이 있습니다. 다른 개발자가 작업 할 코드를 준비 할 때 의도 된 디자인 패턴 내에 머무르게 할 때 많이 사용합니다. 인터페이스는 "계약에 의한 설계"의 일종으로, 귀하의 코드는 귀하가 동의하지 않은 코드에서 비롯 될 수있는 규정 된 API 호출 세트에 응답하는 데 동의합니다.
추상 클래스로부터의 상속은 "is a"관계이며, 항상 원하는 것은 아니며, 인터페이스 구현은 "관계와 같은 역할"입니다. 이 차이는 특정 상황에서 매우 중요 할 수 있습니다.
예를 들어, 다른 많은 클래스가 확장 된 추상 클래스 Account (계정 유형 등)가 있다고 가정 해 보겠습니다. 해당 유형 그룹에만 적용 할 수있는 특정 메소드 세트가 있습니다. 그러나 이러한 계정 하위 클래스 중 일부는 해당 API를 사용할 것으로 예상되는 컨트롤러에 던져 질 수 있도록 버전 관리 가능 또는 목록 가능 또는 편집 가능을 구현합니다. 컨트롤러는 어떤 유형의 객체인지 신경 쓰지 않습니다.
대조적으로 Account에서 확장하지 않고 User 추상 클래스를 말하고 Listable 및 Editable을 구현하지만 Versionable은 구현하지 않는 개체를 만들 수 있습니다.이 개념은 여기서 의미가 없습니다.
이런 식으로, 나는 FooUser 서브 클래스가 계정이 아니라 편집 가능한 객체처럼 행동한다고 말하고있다. 마찬가지로 BarAccount는 Account에서 확장되지만 User 하위 클래스는 아니지만 Editable, Listable 및 Versionable을 구현합니다.
Listable 및 Versionable의 모든 API를 추상 클래스 자체에 추가하면 어수선하고 못생긴 것이 아니라 공통 인터페이스를 Account 및 User에 복제하거나 내 User 객체에 Versionable을 구현하도록 강제 할 수 있습니다. 예외.
인터페이스는 본질적으로 사용자가 만들 수있는 청사진입니다. 클래스가 어떤 메소드를 정의하는지~이 있어야합니다.하지만 이러한 제한을 벗어나는 추가 메서드를 만들 수 있습니다.
코드에 메서드를 추가 할 수 없다는 의미가 무엇인지 확신 할 수 없기 때문입니다. 인터페이스를 추상 클래스 또는 그것을 확장하는 클래스에 적용하고 있습니까?
추상 클래스에 적용된 인터페이스의 메소드는 해당 추상 클래스에서 구현해야합니다. 그러나 해당 인터페이스를 확장 클래스에 적용하면 메서드는 확장 클래스에만 구현해야합니다. 나는 여기서 틀릴 수있다 - 나는 할 수있는만큼 자주 인터페이스를 사용하지 않는다.
필자는 항상 외부 개발자를위한 패턴 또는 올바른 규칙 세트로 인터페이스를 생각했습니다.
PHP에서 인터페이스를 사용합니다.
$object instanceof MyInterface
클래스 Car는 EngineInterface, BodyInterface, SteeringInterface { li> 올>그래서
Car
object ca nowstart()
,stop()
(EngineInterface) 또는goRight()
,goLeft()
(조향 인터페이스)
내가 지금 생각할 수없는 다른 것들
Number 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();
}
추상 클래스와 인터페이스를 비교할 여지는 많지 않습니다. 인터페이스는 구현 될 때 클래스에 공개 인터페이스 세트가 있어야하는 단순한 맵입니다.
제 생각에는 인터페이스가 비 기능 추상 클래스보다 선호되어야합니다. 거기에 퍼포먼스 히트가있을지라도 두 개의 파싱 대신에 인스턴스화 된 오브젝트가 하나 밖에 없으므로 놀라지 않을 것입니다. (물론 확신 할 수는 없지만, 내부 동작에 익숙하지 않습니다. OOP PHP의).
Java와 비교할 때 인터페이스가 덜 유용하고 의미있는 것은 사실입니다. 반대로, PHP6는 리턴 값을위한 타입 힌팅을 포함하여 더 많은 타입 힌팅을 소개 할 것입니다. 이것은 PHP 인터페이스에 약간의 가치를 추가해야합니다.
dr : 인터페이스는 따라야 할 메소드 목록을 정의하고 (API라고 생각하는), 추상 클래스는 기본 / 공통 기능을 제공하며 하위 클래스는 특정 요구 사항을 구체화합니다.
인터페이스는 개발자가 특정 메소드를 구현하도록하기위한 것이 아닙니다. 클래스의 실제 유형을 모르는 경우에도 이러한 클래스가 특정 메소드를 가질 수 있기 때문에 이러한 메소드를 사용할 수 있습니다. 예:
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 ())가 있지만 인터페이스는 구현하지 않습니다.
이 점에서 PHP가 다른지는 기억이 나지 않지만 Java에서는 여러 인터페이스를 구현할 수 있지만 여러 추상 클래스를 상속받을 수는 없습니다. PHP는 같은 방식으로 동작한다고 가정합니다.
PHP에서는 여러 개의 인터페이스를 쉼표로 구분하여 적용 할 수 있습니다 (필자는 깨끗한 해결책을 찾지 못했습니다).
여러 추상 클래스에 관해서는 서로를 확장하는 여러 초록을 가질 수 있습니다 (다시, 나는 그것에 대해 완전히 확신하지는 않지만 이전에 본 적이 있다고 생각합니다). 연장 할 수없는 유일한 방법은 최종 수업입니다.
인터페이스는 코드에 성능 향상이나 그와 같은 어떤 것도주지 않지만 유지 보수성을 높이기 위해 먼 길을 갈 수 있습니다. 추상 클래스 (또는 추상이 아닌 클래스)가 코드에 대한 인터페이스를 설정하는 데 사용될 수 있지만 적절한 인터페이스 (키워드로 정의하고 메소드 서명 만 포함하는 인터페이스)는 정렬하고 읽으십시오.
즉, 클래스를 사용하여 인터페이스를 사용할지 여부를 결정할 때 재량권을 사용하는 경향이 있습니다. 때로는 기본 메소드 구현이나 모든 하위 클래스에 공통적 인 변수가 필요합니다.
물론 다중 인터페이스 구현에 대한 요점은 확실합니다. 여러 인터페이스를 구현하는 클래스가있는 경우 동일한 응용 프로그램에서 해당 클래스의 객체를 다른 유형으로 사용할 수 있습니다.
PHP에 관한 귀하의 질문에 대한 사실은 좀 더 흥미로운 것들을 만듭니다. 인터페이스에 타이핑하는 것은 여전히 PHP에서 필요하지 않습니다. PHP에서는 유형에 관계없이 모든 메소드에 거의 모든 것을 제공 할 수 있습니다. 정적으로 메서드 매개 변수를 입력 할 수 있지만 그 중 일부는 손상되었습니다 (String, 나는 약간의 딸꾹질을 유발합니다). 이것을 다른 대부분의 참조를 입력 할 수 없으며 PHP에서 정적 타이핑을 강제하는 데 많은 가치가 없습니다 (이 지점에서). 그 때문에 인터페이스의 가치PHP에서,이 지점에서보다 강력하게 형식화 된 언어보다 훨씬 적습니다. 그들은 가독성의 이점을 가지고 있지만 그 밖의 것은 거의 없습니다. 다중 구현은 심지어 메소드를 선언하고 구현 자 내에서 본문을 제공해야하기 때문에 유용하지 않습니다.
아래는 PHP 인터페이스의 요점입니다.
예제 코드 :
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.A 클래스는 하나 이상의 인터페이스를 구현할 수 있지만 상속 할 수 있습니다. 단 하나의 추상 클래스에서.
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
희망이 사람을 이해하는 데 도움이됩니다!
인터페이스는 당신의 유전자와 같습니다.
추상적 인 수업은 실제 학부모와 같습니다.
그들의 목적은 유전이지만, 추상 클래스와 인터페이스의 경우 상속 된 것이 더 구체적입니다.