类型提示是一种通知方法的用户他们应该如何调用它们的方法。作为实现该方法的人,它还允许您依赖所传递参数的某些特性。
这是一个没有类型提示的购物车示例
<?php
class Cart {
protected $items = array();
public function addItem($item) {
$this->items[] = $item;
}
}
$cart = new Cart();
$cart->addItem('My Super Cool Toy');
$cart
运行上述内容后,您所拥有的是Cart
一个项目“我的超级酷玩具”的实例。但是,该Cart
对象不知道该项目是什么。它不知道如何与它交互或用它做什么。例如,我如何获得上面购物车的小计?我不能。
这是一个带有类型提示的示例:
<?php
class Cart {
protected $items = array();
public function addItem(Item $item) {
$this->items[] = $item;
}
public function getSubTotal() {
$total = 0;
foreach ($this->items as $item) {
$total += $item->getPrice();
}
return $total;
}
}
class Item {
protected $name;
protected $price;
public function __construct($name, $price) {
$this->name = $name;
$this->price = $price;
}
public function getName() {
return $this->name;
}
public function getPrice() {
return $this->price;
}
}
$cart = new Cart();
$cart->addItem(new Item('My Super Cool Toy', 10.99));
现在我处于完全不同的境地。我知道我Cart
的全是Item
s。我知道我可以getPrice()
的Item
。我可以依赖它,因为你可以调用我的方法的唯一addItem
方法是给我一个Item
对象。
没有类型提示也可以做同样的事情吗?是的。但是,没有什么好的方法可以依赖任何特定的实现。作为调用者,我可能会给你一个 Item 对象。但我也可能会给你一个字符串或一个数字。如果你只有一个字符串或一个数字,你怎么能确定地给我一个价格?
现在让我们让它变得更好一点
并快速进入接口编码。假设我有玩具类型:遥控车和洋娃娃。大概,我们以不同的方式玩它们。在这种情况下,一个“项目”对象不起作用,因为它们可以做不同的事情。但是,它们都表现出相同类型的行为。它们都是玩具。所以让我们为此创建一个接口:
<?php
interface Toy {
public function play();
}
让我们为我们的玩具创建一些具体的类:
<?php
class RemoteControlledCar implements Toy {
public function play() {
print "I'm driving a car";
}
}
class Doll implements Toy {
public function play() {
print "GI Joe";
}
}
现在,我们要将玩具存放在玩具箱中:
<?php
class ToyBin {
protected $toys = array();
public function addToy(Toy $toy) {
$this->toys[] = $toy;
}
public function playWithMyToys() {
foreach ($this->toys as $toy) {
$toy->play();
}
}
}
看看那,你已经成功地正确编程了。你知道你有一个装满玩具物品的玩具箱。你不必关心它们是什么类型的玩具,也不必关心你将如何与它们互动。你只知道你可以用它们做某些事情(在这种情况下,play
用它们)。正因为如此,你有一个可以依赖的界面。
为什么这更好?
接口确实是编程的方式,原因有几个
- 它们只需要界面创建者的很少努力。接口不需要具有任何功能。它只是作为其他人实施的“合同”。
- 它们让您依赖可用的特定功能。在我的示例中,您知道可以使用任何使其进入您的“玩具” 。而且你不必担心如何。
ToyBin
play()
- 它们允许在不牺牲代码质量的情况下灵活地实现。您可以对可以以任何方式玩的任何类型的玩具进行编程。
希望这有助于澄清问题。