15

我在想出一个好的结构来构建我的类和对象时遇到了一些问题。在下面的代码中,我使用一个接口来定义我的类方法,但我还想将一个数据库连接传递给我的构造函数,以便类可以使用这个连接。当我在下面编码时将构造函数放置在我的类中和我的接口中的方法是否正确?

interface IDataItem
{
    public function saveItem(Item $theItem);
}

class DataItem implements IDataItem
{
    public function __construct(Database $database) 
    { 
        $this->database = $database;
    }

    public function saveItem(Item $item) 
    {       
        //save the item
    }
}

$db = new Database(); //from a database class
$dataItem = new DataItem($db);          
$dataItem->saveItem($anItem);
4

6 回答 6

22

虽然在技术上可以将构造函数添加到接口,但接口不应定义构造函数,因为那将是实现类的实现细节。接口应该只定义其他协作者可以调用的公共 API。也就是说,他们不应该强制执行特定的实现。

如果您在接口中放置一个请求数据库连接的构造函数,您会将具体类限制为构造函数签名中的依赖项。如果实现接口的具体类需要不同的(因为它保存到 Web 服务)或额外的(可能是记录器)依赖项,则您无法使其与您的接口一起使用。

于 2012-11-07T14:06:35.757 回答
12

我个人认为您不应该将构造函数放在接口中,因为您永远不会通过调用构造函数来创建新对象而不知道您正在使用哪个实现。

你的代码有错误,接口中的方法不能有实现,它需要只是一个声明,像这样

interface IDataItem
{
    public function saveItem($theItem);
}
于 2012-11-07T13:50:29.937 回答
7

这有点离题了,但我认为它强调了在接口中定义构造函数可能有用的情况。

可以在不知道其类的情况下实例化对象。这是一个简单的例子:

interface Animal
{
    public function __construct($name);
    public function speak();
    public function getName();
}

class Cat implements Animal
{
    protected $name=null;
    public function __construct($name){ $this->name=$name; }
    public function speak(){ echo 'meow'; }
    public function getName(){ return $this->name;}
}

class Dog implements Animal
{
    protected $name=null;
    public function __construct($name){ $this->name=$name; }
    public function speak(){ echo 'woof'; }
    public function getName(){ return $this->name;}
}

$animals=Array(array('name'=>'Felix','type'=>'Cat'),array('name'=>'Fido','type'=>'Dog'));

foreach($animals as $a)
{
    $theAnimal=new $a['type']($a['name']);
    echo '<p>speak, '.$theAnimal->getName().'</p><p>';
    $theAnimal->speak();
    echo '</p>';
}

我已经使用这样的东西进行 url 路由,以将 url 与其顶级控制器匹配。

于 2016-06-15T00:36:25.927 回答
3

根据 PHP 文档:

“请注意,可以在接口中声明构造函数,这在某些情况下可能很有用,例如供工厂使用。”

关键是构造函数不必用具体类定义,但可以用接口定义,例如:

interface TestInterface {
    public function __construct(interfaceA, interfaceB);
}

然后实现TestInterface的类用interfaceA和interfaceB的具体实现来定义它的构造函数:

class Test implements TestInterface {
    public function __construct(testA, testB);
}

其中 testA 可能类似于:

class testA implements interfaceA {
    public function doStuff() {
        //...
    }
}
于 2019-11-06T09:58:20.533 回答
2

接口只是强制执行可能不相关的类都将实现相同方法的契约。

由于在构造时必须明确知道类,所以将构造函数放在接口中是没有用的。你永远不会通过接口调用构造函数。您当前的解决方案是正确的。

于 2012-11-07T13:49:00.720 回答
-3

创建一个变量来保存类中的数据库句柄。

于 2012-11-07T13:48:32.720 回答