我有一些问题想出一个好的结构来构建我的类和对象。 在下面的代码中,我使用一个接口来定义我的类方法,但我也想将数据库连接传递给我的构造函数,以便类具有此连接。 它是否正确,因为我在下面编写它,构造函数放在我的类和我的界面中的方法?
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);
答案 0 :(得分:11)
虽然在技术上可以将构造函数添加到接口,但接口不应该定义构造函数,因为这将是实现类的实现细节。接口应该只定义其他协作者可以调用的公共API。也就是说,他们不应该强制执行特定的实现。
如果您在接口中放置了一个构造函数请求数据库连接,那么您将具体类限制为构造函数签名中的依赖项。如果实现接口的具体类需要不同(因为它保存到Web服务)或其他(可能是Logger)依赖项,则无法使用您的接口。
答案 1 :(得分:8)
我个人认为你不应该把构造函数放在接口中,因为你永远不会通过调用构造函数来创建一个新对象而不知道你正在使用哪个实现。
你的代码中有一个错误,接口中的方法不能有实现,它只需要一个声明,就像这样
interface IDataItem
{
public function saveItem($theItem);
}
答案 2 :(得分:4)
这有点偏离主题,但我认为它强调了在界面中定义构造函数可能有用的情况。
可以在不知道其类的情况下实例化对象。这是一个简单的例子:
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>';
}
我已经使用类似这样的内容进行网址路由,以便将网址与其顶级控制器进行匹配。
答案 3 :(得分:2)
接口只是一个强制执行可能不相关的类都将实现相同方法的契约。
由于在构造类时必须明确地知道类,因此将构造函数放在接口中是没用的。您永远不会通过接口调用构造函数。您当前的解决方案是正确的。
答案 4 :(得分:0)
根据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() {
//...
}
}
答案 5 :(得分:-3)
创建一个变量来保存类中的db句柄。