类型提示是一种告知用户您的方法如何他们应该调用它们的方式。它还允许您作为实现该方法的人,依赖您正在传递的参数的某些特性。
这是一个没有类型提示的购物车示例
<?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 充满了Items。我知道我可以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() 一起使用。而且您不必担心如何操作。
- 它们允许在不牺牲代码质量的情况下灵活地实施。您可以对任何可以以任何方式玩的玩具进行编程。
希望这有助于解决问题。