복붙노트

PHP에서 두 개 이상의 클래스를 사용하여 클래스를 확장 할 수 있습니까?

PHP

PHP에서 두 개 이상의 클래스를 사용하여 클래스를 확장 할 수 있습니까?

필요한 기능을 가진 여러 클래스가 있지만 조직을 위해 별도로 저장하려는 경우 클래스를 확장하여 둘 다 가질 수 있습니까?

즉 클래스 a는 b 확장 c

편집 : 클래스를 한 번에 하나씩 확장하는 방법을 알고 있지만 즉시 여러 기본 클래스를 사용하여 클래스를 확장 할 수있는 메서드를 찾고 있어요 - AFAIK PHP에서는이 작업을 수행 할 수 없지만 주위에 방법이 있어야합니다. 클래스 c는 b를, 클래스 b는

해결법

  1. ==============================

    1.귀하의 편집 답변 :

    귀하의 편집 답변 :

    정말로 다중 상속을 가짜로 만들고 싶다면 마술 함수 __call ()을 사용할 수 있습니다.

    이것은 클래스 A 사용자의 관점에서 작동하지만 추악합니다.

    class B {
        public function method_from_b($s) {
            echo $s;
        }
    }
    
    class C {
        public function method_from_c($s) {
            echo $s;
        }
    }
    
    class A extends B
    {
      private $c;
    
      public function __construct()
      {
        $this->c = new C;
      }
    
      // fake "extends C" using magic function
      public function __call($method, $args)
      {
        $this->c->$method($args[0]);
      }
    }
    
    
    $a = new A;
    $a->method_from_b("abc");
    $a->method_from_c("def");
    

    "abcdef"를 인쇄합니다.

  2. ==============================

    2.두 개의 기본 클래스를 확장하는 클래스는 가질 수 없습니다. 당신은 가질 수 없었습니다.

    두 개의 기본 클래스를 확장하는 클래스는 가질 수 없습니다. 당신은 가질 수 없었습니다.

    // this is NOT allowed (for all you google speeders)
    Matron extends Nurse, HumanEntity
    

    그러나 다음과 같은 계층 구조를 가질 수 있습니다 ...

    Matron extends Nurse    
    Consultant extends Doctor
    
    Nurse extends HumanEntity
    Doctor extends HumanEntity
    
    HumanEntity extends DatabaseTable
    DatabaseTable extends AbstractTable
    

    등등.

  3. ==============================

    3.PHP 5.4에서 사용할 수있는 특성을 사용할 수 있습니다.

    PHP 5.4에서 사용할 수있는 특성을 사용할 수 있습니다.

    특성은 PHP와 같은 단일 상속 언어에서 코드 재사용을위한 메커니즘입니다. 특성은 개발자가 다른 클래스 계층에있는 여러 개의 독립적 인 클래스에서 메서드 집합을 자유롭게 다시 사용할 수있게하여 단일 상속의 일부 제한을 줄이기위한 것입니다. 특성과 클래스의 조합의 의미는 복잡성을 줄이고 다중 상속 및 Mixins과 관련된 일반적인 문제를 피하는 방식으로 정의됩니다.

    그들은 Perl 6, Squeak, Scala, Slate 및 Fortress와 같은 최신 버전의 언어로 통합하여 더 나은 구성 및 재사용을 지원할 수있는 잠재력으로 인정 받고 있습니다. 형질 또한 자바와 C #으로 이식되었습니다.

    추가 정보 : https://wiki.php.net/rfc/traits

  4. ==============================

    4.클래스는 메서드 모음 일뿐입니다. 클래스는 상태를 변경하는 상태 (필드)와 동작 (메서드)을 모두 가진 추상 개념을 나타냅니다. 상속을 사용하여 원하는 OO 디자인과 같은 몇 가지 원하는 동작을 얻으십시오. 많은 언어가 다중 상속을 허용하지 않는 이유는 정확히 "스파게티 상속"을 방지하기 위해서입니다. 즉, 각각 필요한 메서드가 있기 때문에 3 개의 클래스를 확장하고 100 개의 메서드와 20 개의 필드를 상속하는 클래스이며, 5 개만 사용합니다.

    클래스는 메서드 모음 일뿐입니다. 클래스는 상태를 변경하는 상태 (필드)와 동작 (메서드)을 모두 가진 추상 개념을 나타냅니다. 상속을 사용하여 원하는 OO 디자인과 같은 몇 가지 원하는 동작을 얻으십시오. 많은 언어가 다중 상속을 허용하지 않는 이유는 정확히 "스파게티 상속"을 방지하기 위해서입니다. 즉, 각각 필요한 메서드가 있기 때문에 3 개의 클래스를 확장하고 100 개의 메서드와 20 개의 필드를 상속하는 클래스이며, 5 개만 사용합니다.

  5. ==============================

    5.곧 믹스 인을 추가 할 계획이 있다고 믿습니다.

    곧 믹스 인을 추가 할 계획이 있다고 믿습니다.

    그러나 그때까지 받아 들여진 대답으로 가십시오. "확장 가능"클래스를 만들기 위해 조금 추상화 할 수 있습니다.

    class Extendable{
      private $extender=array();
    
      public function addExtender(Extender $obj){
        $this->extenders[] = $obj;
        $obj->setExtendee($this);
      }
    
      public function __call($name, $params){
        foreach($this->extenders as $extender){
           //do reflection to see if extender has this method with this argument count
           if (method_exists($extender, $name)){
              return call_user_func_array(array($extender, $name), $params);
           }
        }
      }
    }
    
    
    $foo = new Extendable();
    $foo->addExtender(new OtherClass());
    $foo->other_class_method();
    

    이 모델에서 "OtherClass"는 $ foo에 대해 '알아'옵니다. OtherClass에는이 관계를 설정하기 위해 "setExtendee"라는 public 함수가 있어야합니다. 그런 다음 메서드가 $ foo에서 호출되면 내부적으로 $ foo에 액세스 할 수 있습니다. 그러나 실제 확장 클래스처럼 개인 / 보호 된 메소드 / 변수에 액세스 할 수는 없습니다.

  6. ==============================

    6.필자는 라이브러리 / 프레임 워크와 달리 프로젝트에서 상속을 방해하는 몇 가지 기사를 읽었으며 구현에 반대하여 agaisnt 인터페이스를 프로그래밍하도록 권장했습니다. 그들은 또한 작곡을 통해 OO를지지합니다 : 클래스 a와 b에서 함수가 필요한 경우이 유형의 멤버 / 필드가있는 c를 만듭니다.

    필자는 라이브러리 / 프레임 워크와 달리 프로젝트에서 상속을 방해하는 몇 가지 기사를 읽었으며 구현에 반대하여 agaisnt 인터페이스를 프로그래밍하도록 권장했습니다. 그들은 또한 작곡을 통해 OO를지지합니다 : 클래스 a와 b에서 함수가 필요한 경우이 유형의 멤버 / 필드가있는 c를 만듭니다.

    class C
    {
        private $a, $b;
    
        public function __construct($x, $y)
        {
            $this->a = new A(42, $x);
            $this->b = new B($y);
        }
    
        protected function DoSomething()
        {
            $this->a->Act();
            $this->b->Do();
        }
    }
    
  7. ==============================

    7.@Franck에 의해 현재 받아 들여지는 대답은 작동하지만 실제로는 다중 상속이 아니라 범위에서 정의 된 클래스의 자식 인스턴스이며 __call () 약식도 있습니다 - $ this-> childInstance-> method (args) 어디서나 "확장 된"클래스에서 ExternalClass 클래스 메서드가 필요합니다.

    @Franck에 의해 현재 받아 들여지는 대답은 작동하지만 실제로는 다중 상속이 아니라 범위에서 정의 된 클래스의 자식 인스턴스이며 __call () 약식도 있습니다 - $ this-> childInstance-> method (args) 어디서나 "확장 된"클래스에서 ExternalClass 클래스 메서드가 필요합니다.

    아니, 당신은 할 수 없다 각각, 실제로, 확장 키워드의 설명서로 말합니다 :

    그러나 @adam이 올바르게 제안 했으므로 다중 계층 상속을 사용하는 것이 금지되지 않습니다.

    당신은 하나의 클래스를 다른 클래스와 다른 클래스로 확장 할 수 있습니다.

    이것에 대한 아주 간단한 예제는 다음과 같습니다.

    class firstInheritance{}
    class secondInheritance extends firstInheritance{}
    class someFinalClass extends secondInheritance{}
    //...and so on...
    

    이미 알고 계시 겠지만, 프로세스에 포함 된 모든 클래스를 제어 할 수 있다면 계층별로 여러 가지 (2+ 개)의 intehritance 만 수행 할 수 있습니다. 즉,이 솔루션을 적용 할 수 없습니다. 빌트인 클래스 나 단순히 편집 할 수없는 클래스가 있습니다. 그렇게하고 싶다면 @Franck 솔루션 - 하위 인스턴스가 있습니다.

    ... 그리고 마지막으로 몇 가지 출력 예제 :

    class A{
      function a_hi(){
        echo "I am a of A".PHP_EOL."<br>".PHP_EOL;  
      }
    }
    
    class B extends A{
      function b_hi(){
        echo "I am b of B".PHP_EOL."<br>".PHP_EOL;  
      }
    }
    
    class C extends B{
      function c_hi(){
        echo "I am c of C".PHP_EOL."<br>".PHP_EOL;  
      }
    }
    
    $myTestInstance = new C();
    
    $myTestInstance->a_hi();
    $myTestInstance->b_hi();
    $myTestInstance->c_hi();
    

    어느 출력

    I am a of A 
    I am b of B 
    I am c of C 
    
  8. ==============================

    8.

    <?php
    // what if we want to extend more then one class?
    
    Abstract class ExtensionBridge
    {
        // array containing all the extended classes
        private $_exts = array();
        public $_this;
    
        function __construct(){$_this = $this;}
    
        public function addExt($object)
        {
            $this->_exts[]=$object;
        }
    
        public function __get($varname)
        {
            foreach($this->_exts as $ext)
            {
                if(property_exists($ext,$varname))
                return $ext->$varname;
            }
        }
    
        public function __call($method,$args)
        {
            foreach($this->_exts as $ext)
            {
                if(method_exists($ext,$method))
                return call_user_method_array($method,$ext,$args);
            }
            throw new Exception("This Method {$method} doesn't exists");
        }
    
    
    }
    
    class Ext1{
    private $name="";
    private $id="";
    public function setID($id){$this->id = $id;}
    public function setName($name){$this->name = $name;}
    public function getID(){return $this->id;}
    public function getName(){return $this->name;}
    }
    
    class Ext2{
    private $address="";
    private $country="";
    public function setAddress($address){$this->address = $address;}
    public function setCountry($country){$this->country = $country;}
    public function getAddress(){return $this->address;}
    public function getCountry(){return $this->country;}
    }
    
    class Extender extends ExtensionBridge
    {
        function __construct()
        {
            parent::addExt(new Ext1());
            parent::addExt(new Ext2());
        }
    
        public function __toString()
        {
            return $this->getName().', from: '.$this->getCountry();
        }
    }
    
    $o = new Extender();
    $o->setName("Mahdi");
    $o->setCountry("Al-Ahwaz");
    echo $o;
    ?>
    
  9. ==============================

    9.특성을 기본 클래스로 사용하십시오. 그런 다음 상위 클래스에서 사용하십시오. 그것을 확장하십시오.

    특성을 기본 클래스로 사용하십시오. 그런 다음 상위 클래스에서 사용하십시오. 그것을 확장하십시오.

    trait business{
      function sell(){
    
      }
    
      function buy(){
    
      }
    
      function collectMoney(){
      }
    
    }
    
    trait human{
    
       function think(){
    
       }
    
       function speak(){
    
       }
    
    }
    
    class BusinessPerson{
      use business;
      use human;
      // If you have more traits bring more
    }
    
    
    class BusinessWoman extends BusinessPerson{
    
       function getPregnant(){
    
       }
    
    }
    
    
    $bw = new BusinessWoman();
    $bw ->speak();
    $bw->getPregnant();
    

    지금보십시오 비즈니스 여성은 논리적으로 상속 된 비즈니스 및 인간 모두입니다.

  10. ==============================

    10.다중 상속은 인터페이스 수준에서 작동하는 것 같습니다. 나는 PHP 5.6.1에서 테스트를했다.

    다중 상속은 인터페이스 수준에서 작동하는 것 같습니다. 나는 PHP 5.6.1에서 테스트를했다.

    다음은 작동하는 코드입니다.

    <?php
    
    
    interface Animal
    {
        public function sayHello();
    }
    
    
    interface HairyThing
    {
        public function plush();
    }
    
    interface Dog extends Animal, HairyThing
    {
        public function bark();
    }
    
    
    class Puppy implements Dog
    {
        public function bark()
        {
            echo "ouaf";
        }
    
        public function sayHello()
        {
            echo "hello";
        }
    
        public function plush()
        {
            echo "plush";
        }
    
    
    }
    
    
    echo PHP_VERSION; // 5.6.1
    $o = new Puppy();
    $o->bark();
    $o->plush();
    $o->sayHello(); // displays: 5.6.16ouafplushhello
    

    가능하다고 생각하지는 않았지만 SwiftMailer 소스 코드 Swift_Transport_IoBuffer 클래스에서 다음과 같은 정의가 있습니다.

    interface Swift_Transport_IoBuffer extends Swift_InputByteStream, Swift_OutputByteStream
    

    나는 아직 그걸 가지고 놀지 못했지만, 나는 그것을 나누는 것이 재미있을 것이라고 생각했습니다.

  11. ==============================

    11.방금 "다중 상속"문제를 해결했습니다.

    방금 "다중 상속"문제를 해결했습니다.

    class Session {
        public $username;
    }
    
    class MyServiceResponsetype {
        protected $only_avaliable_in_response;
    }
    
    class SessionResponse extends MyServiceResponsetype {
        /** has shared $only_avaliable_in_response */
    
        public $session;
    
        public function __construct(Session $session) {
          $this->session = $session;
        }
    
    }
    

    이 방법으로 MyServiceResponsetype을 확장 한 SessionResponse 내부에서 세션을 조작 할 수있는 능력이 있으며 여전히 Session을 자체적으로 처리 할 수 ​​있습니다.

  12. ==============================

    12.PHP 5.4에서 발표 된 PHP의 특성을 사용하여이를 수행 할 수 있습니다.

    PHP 5.4에서 발표 된 PHP의 특성을 사용하여이를 수행 할 수 있습니다.

    다음은 빠른 자습서입니다. http://culttt.com/2014/06/25/php-traits/

  13. ==============================

    13.PHP는 아직 다중 클래스 상속을 지원하지 않지만 다중 인터페이스 상속을 지원합니다.

    PHP는 아직 다중 클래스 상속을 지원하지 않지만 다중 인터페이스 상속을 지원합니다.

    몇 가지 예를 보려면 http://www.hudzilla.org/php/6_17_0.php를 참조하십시오.

  14. ==============================

    14.PHP는 다중 상속을 허용하지 않지만, 다중 인터페이스를 구현하는 것으로 할 수 있습니다. 구현이 "무거운"경우 별도의 클래스에있는 각 인터페이스에 골격 구현을 제공하십시오. 그런 다음 모든 객체 클래스를 객체 포함을 통해 이러한 스켈 레탈 구현에 위임 할 수 있습니다.

    PHP는 다중 상속을 허용하지 않지만, 다중 인터페이스를 구현하는 것으로 할 수 있습니다. 구현이 "무거운"경우 별도의 클래스에있는 각 인터페이스에 골격 구현을 제공하십시오. 그런 다음 모든 객체 클래스를 객체 포함을 통해 이러한 스켈 레탈 구현에 위임 할 수 있습니다.

  15. ==============================

    15.당신이 달성하고자하는 것을 정확히 알지 못한다면,이 경우에는 상속이 아닌 구성을 사용하도록 응용 프로그램을 재 설계 할 가능성을 조사하는 것이 좋습니다.

    당신이 달성하고자하는 것을 정확히 알지 못한다면,이 경우에는 상속이 아닌 구성을 사용하도록 응용 프로그램을 재 설계 할 가능성을 조사하는 것이 좋습니다.

  16. ==============================

    16.항상 좋은 아이디어는 기능을 가진 부모 클래스를 만드는 것입니다. 즉 부모에게이 모든 기능을 추가하는 것입니다.

    항상 좋은 아이디어는 기능을 가진 부모 클래스를 만드는 것입니다. 즉 부모에게이 모든 기능을 추가하는 것입니다.

    이 계층을 사용하는 모든 클래스를 "이동"합니다. 필자는 특정 기능을 다시 작성해야합니다.

  17. ==============================

    17.함수가 공개되어 있는지 확인하려면이 항목을 참조하십시오. https://stackoverflow.com/a/4160928/2226755

    함수가 공개되어 있는지 확인하려면이 항목을 참조하십시오. https://stackoverflow.com/a/4160928/2226755

    그리고 많은 인수에 대해 call_user_func_array (...) 메소드를 사용하십시오.

    이렇게 :

    class B {
        public function method_from_b($s) {
            echo $s;
        }
    }
    
    class C {
        public function method_from_c($l, $l1, $l2) {
            echo $l.$l1.$l2;
        }
    }
    
    class A extends B {
        private $c;
    
        public function __construct() {
            $this->c = new C;
        }
    
        public function __call($method, $args) {
            if (method_exists($this->c, $method)) {
                $reflection = new ReflectionMethod($this->c, $method);
                if (!$reflection->isPublic()) {
                    throw new RuntimeException("Call to not public method ".get_class($this)."::$method()");
                }
    
                return call_user_func_array(array($this->c, $method), $args);
            } else {
                throw new RuntimeException("Call to undefined method ".get_class($this)."::$method()");
            }
        }
    }
    
    
    $a = new A;
    $a->method_from_b("abc");
    $a->method_from_c("d", "e", "f");
    
  18. ==============================

    18.프로그래밍 언어로서의 PHP의 문제점 중 하나는 하나의 상속만을 가질 수 있다는 것입니다. 즉, 클래스는 하나의 다른 클래스에서만 상속받을 수 있습니다.

    프로그래밍 언어로서의 PHP의 문제점 중 하나는 하나의 상속만을 가질 수 있다는 것입니다. 즉, 클래스는 하나의 다른 클래스에서만 상속받을 수 있습니다.

    그러나 많은 시간을 여러 클래스에서 상속하는 것이 유익 할 것입니다. 예를 들어, 코드 중복을 방지하기 위해 여러 클래스의 메소드를 상속하는 것이 바람직 할 수 있습니다.

    이 문제는 종종 합리적이지 않은 상속에 대한 가족력이 긴 클래스로 이어질 수 있습니다.

    PHP 5.4에서 새로운 언어 기능이 Traits로 추가되었습니다. Trait은 Trait 클래스를 기존 클래스에 혼합 할 수있는 Mixin과 비슷합니다. 즉, 다중 상속 문제를 피하면서 코드 중복을 줄이고 이점을 얻을 수 있습니다.

    형질

  19. ==============================

    19.인터페이스는 실제로 나를 똑같은 방식으로 다시 구현하도록 강요하고 다시 알림 또는 TODO 주석으로 사용하기 때문에 논리적 의미를 형성하는 데 무의미합니다. 그것은 나쁘지 않다고 말하지만 논리적 인면은 파이썬이 아마이 문제에 대한 최상의 해결책이라고 생각하는 다이아몬드 문제를 피하는 것입니다. 함수 본문을 계속해서 다시 작성할 필요는 없습니다. 실행할 상위 호출자를 선택할 수 있습니다.

    인터페이스는 실제로 나를 똑같은 방식으로 다시 구현하도록 강요하고 다시 알림 또는 TODO 주석으로 사용하기 때문에 논리적 의미를 형성하는 데 무의미합니다. 그것은 나쁘지 않다고 말하지만 논리적 인면은 파이썬이 아마이 문제에 대한 최상의 해결책이라고 생각하는 다이아몬드 문제를 피하는 것입니다. 함수 본문을 계속해서 다시 작성할 필요는 없습니다. 실행할 상위 호출자를 선택할 수 있습니다.

    예를 들어 Herbivore 클래스와 Carnivore 클래스와 Omnivore 클래스 모두 param 음식을 먹는 함수를 먹는다면,이 경우 Omnivore에서 먹기를 다시 먹어야합니다. Herbivore 먹거나 Carnivore 먹는 잡식 동물 먹는 것보다 .

    class Herbivore:
    def eat(self, food):
        print("Food is supposed to be vegan")
    
    
    class Carnivore:
    def eat(self, food):
        print("Food is supposed to be meaty")
    
    
    
    class Omnivore(Carnivore, Herbivore):
    def eat(self, food):
        #Test the food type and call function for either 
        #Carnivore.eat(food)
        #Herbivore.eat(food)
        #There is no actual re-implementation of the action
        print("Food has to either bee meaty or vegan")
    
  20. ==============================

    20.클래스 A는 B {}를 확장합니다.

    클래스 A는 B {}를 확장합니다.

    클래스 B는 C {}를 확장합니다.

    그런 다음 A가 B와 C를 모두 확장했습니다.

  21. from https://stackoverflow.com/questions/356128/can-i-extend-a-class-using-more-than-1-class-in-php by cc-by-sa and MIT license