2013-07-24 2 views
10

Я начал писать класс-оболочку для предопределенного пакета php. Вот классы:instanceof error in php wrapper class

class phpclass1 
    :: ping() 
    :: __construct(array $options) 
    :: clear() 
    :: addDoc(phpclass2 $string) 

... 

class phpclass2 
    :: __construct() 
    :: update() 
... 

Здесь приведены классы-оболочки, которые я написал для выше 2 класса:

class wrapper1 { 
    private $conn; 

    public function __construct(phpclass1 $object) { 
     $this->conn = $object; 
    } 

    public function add(wrapper2 $document) { 
     return $this->conn->addDoc($document); 
    } 
} 

class wrapper2 extends phpclass2 { 
    private $doc; 
    public function __construct() { 
     $this->doc = new phpclass2(); 
    }  
} 

Here's how I'm using them: 
$options = array (...); 
$object = new phpclass1($options); 
$conn = new wrapper1($object); 
$doc = new wrapper2(); 
.... 
.... 
$conn->add($doc); 

Все работало, пока я не использовал функцию add. Он дает ошибку: Argument 1 passed to phpclass1::addDoc() must be an instance of phpclass2, instance of wrapper2 given

Что мне не хватает? Я много пробовал, но полностью проиграл.

+8

Аргумент 'phpclass1 :: addDoc()' имеет тип-тип как 'phpclass2', и вы передаете его' $ document', что является 'wrapper2'. Если 'wrapper2' не расширяет' phpclass2', подсказка типа не будет выполнена. –

+0

@MichaelBerkowski: Я пробовал это, но была некоторая ошибка. (Я предполагаю, что пакет php, который я использую, не может содержать такое дублирование/клонирование экземпляров). Поэтому мне было интересно, может ли быть какой-то другой способ. – xan

+2

Нам нужно будет увидеть, что такое ошибка. Пока вы не пытаетесь переопределить методы 'final' или' private', вы должны иметь возможность расширить класс save для некоторого потенциально экзотического случая. –

ответ

2

Вы определили

class phpclass1 :: addDoc(phpclass2 $string) 

Этот метод предполагает, что аргумент, чтобы быть объектом phpclass2, но вы передаете

return $this->conn->addDoc($document); 

через

$conn->add($doc); 

и $ док является объект обертки2 не phpclass2

Чтобы исправить добавить новый публичный метод

wrapper2::getDoc() 

public function add(wrapper2 $document) { 
    return $this->conn->addDoc($document->getDoc()); 
} 
+0

Он верен, вы проходите неправильный тип, вы также можете решить это, сделав' wrapper2' extend 'phpclass2'. Также см. [Прокси-шаблон] (http://www.mwop.net/blog/263-Proxies-in-PHP.html) – NDM

+0

@NickyDeMaeyer: я редактировал мой код, чтобы «расширять» класс 'wrapper2', чтобы 'phpclass2'. Но все же он дает ошибку: 'phpclass1 :: addDoc(): wrapper2 недействителен.' – xan

+0

Вы по-прежнему передаете неправильный объект $ this-> conn-> addDoc(). Вы передаете объект wrapper2 вместо этого, если объект phpclass2. Решение с добавлением нового общедоступного метода настолько просто, почему вы его не реализуете? –

0

Ваш phpclass1::addDoc имеет тип намекал брать только объект phpclass2. Ваш метод wrapper1::add принимает объект типа wrapper2, а затем передает его на phpclass1::addDoc. Основываясь на ваших классах, это противоречиво, так как wrapper2 не является экземпляром phpclass2.

Вы должны изменить свой typehint или позволить wrapper2 класс обеспечить phpclass2 объект, который он оберточной или расширяющий wrapper2 так, что она является экземпляром phpclass2

+0

Я редактировал свой код, чтобы 'расширять' класс 'wrapper2' до' phpclass2'. Но все же это дает ошибку: 'phpclass1 :: addDoc(): wrapper2 недействителен.' – xan

2

ПРОБЛЕМА

Вы тип hinting wrapper1 метод принять тип wrapper2 все хорошо и хорошо. Внутри метода wrapper1 вы объявляете

public function add(wrapper2 $document) { 
     return $this->conn->addDoc($document); 
    } 

где $conn определяется как phpclass1 экземпляра. Проблема возникает, как вы называете

return $this->conn->addDoc($document); 

который ожидает типа phpclass2 но $ документа на самом деле типа wrapper2 как мы принимаем его, вы не можете редактировать либо phpclass1 ИЛИ phpclass2 вам нужно будет модифицировать классы-оболочки.

Растворы

раствор 1

либо изменить wrapper2 to be

class wrapper2 { 
    private $doc; 
    public function __construct() { 
     $this->doc = new phpclass2(); 
    } 
    public function GetDoc() 
    { 
     return $this->doc; 
    } 
} 

и использовать следующим образом

$conn->add($doc->GetDoc()); 

Решение 2

изменить подпись $ doc; внутри wrapper2 к public и использовать следующим образом

$conn->add($doc->doc); 

для получения дополнительной информации о typehinting в PHP посмотреть на странице документации для ее php type hinting

одна вещь, чтобы рассмотреть это сделать вам нужно/желательно вводить намек, не выставляя аргумент за/против, поскольку его уже обсуждали подробно, просто вопрос, который вы можете задать.

Если ответ да, то вы можете прочитать следующую link, который говорит о хороших отношениях и причин использовать тип намекая

Я надеюсь, что это помогает

+0

Большое спасибо. Он работает, хотя и выдает ошибку для 'destruct':' Warning: phpclass2 :: __ destruct(): ' – xan

+0

В совершенно другой заметке есть ли другой способ реализации классов-оболочек? – xan

+0

в зависимости от ваших мнений о них вы могли бы использовать интерфейсы в сочетании с вашими классами обертки, но насколько мне известно, я сделал бы то же самое, что и вы сделали. Что касается предупреждения о разрушении, то для чего это полная ошибка? –

0

Изменение public function add(wrapper2 $document) к public function add($document)type hinting является вопрос ,