Strong Typing & Water Fowl 强类型和小鸭子

In the previous chapters, we covered the basics of dependency injection: what it is; how it is accomplished; and several of benefits. The examples in the previous chapters also demonstrated the injection of interface into our classes, so before proceeding further, it will be beneficial to talk about interfaces in depth, as many PHP developers are not familiay with them.

在之前的章节里,涵盖了依赖注入的基础知识:什么是依赖注入;如何实现依赖注入;依赖注入有什么好处。之前章节里面的例子也模拟了将 interface 注入到 classes 里面的过程。在我们继续学习之前,有必要深入讲解一下接口,而这正是很多 PHP 开发者所不熟悉的。

Before I was a PHP programmer, I was a .NET programmer. Do I love pain or what? In .NET, interfaces are everywhere. In fact, many interfaces are defined as part of the core .NET framework itself, and for good reason: many of the .NET languages, such as C# and VB.NET, are strongly typed. In general, you must define the type of object or primitive you will be passing into a method. For example, consider the following C# method:

在我成为 PHP 程序员之前,我是写 .NET 的。在 .NET 里可到处都是接口。事实上很多接口是定义在 .NET 框架核心中了,一个好的理由是:很多 .NET 语言比如 C# 和 VB.NET 都是强类型的。 也就是说,你在给一个函数传值,要么传原生类型对象,要么就必须给这个对象一个明确的类型定义。比如考虑以下 C# 方法:

public int BillUser(User user)
    this.biller.bill(user.GetId(), this.amount)

Note that we were forced to define not only what type of arguments we will be passing to the method, but also what the method itself will be returning. C# is encouraging type safety. We will not be allowed to pass anything other than an User object into out BillUser method

注意在这里, 我们不仅要定义传进去的参数是什么类型的,还要定义这个方法返回值是什么类型的。 C# 鼓励类型安全。除了指定的 User 对象,它不允许我们传递其他类型的对象到 BillUser 方法中。

However, PHP is generally a duck typed language. In a duck typed language, an object's avaliable methods determine the way it may be used, rather than its inheritance from a class or implementation of an interface. Let's look at an example:

然而 PHP 是一种鸭子类型的语言。所谓鸭子类型的语言,一个对象可用的方法取决于使用方式,而非这个方法从哪儿继承或实现。来看个例子:

public function billUser($user)
    $this->biller->bill($user->getId(), $this->amount);

In PHP, we did not have to tell the method what type of argument to expect. In fact, we can pass any type, so long as the object responds to the getId method. This is an example of duck typing. If the object looks like a duck, quacks like a duck, it must be a duck. Or, in this case, if the object looks like a user, and acts like a user, it must be one.

在 PHP 里面,我们不必告诉一个方法需要什么类型的参数。实际上我们传递任何类型的对象都可以,只要这个对象能响应 getId 的调用。这里有个关于鸭子类型(下文译作:弱类型)的解释:如果一个东西看起来像个鸭子,叫声也像鸭子叫,那他就是个鸭子。 换言之在程序里,一个对象看上去是个 User ,方法响应也像个 User ,那他就是个 User 。

But, does PHP have any strongly typed style features? Of course! PHP has a mixture of both strong and duck typed constructs. To illustrate this, let's re-write our billUser method:

不过 PHP 到底有没有任何强类型功能呢?当然有!PHP 混合了强类型和弱类型的结构。为了说明这点,咱们来重写一下 billUser 方法:

public function billUser(User $user)
    $this->biller->bill($user->getId(), $amount);

After adding the User type-hint to our method signature, we can now gurantee that all objects passed to billUser either are a User instance, or extend the User class.

给方法加上了加上了 User 类型提示后, 我们可以确信的说所有传入 billUser 方法的参数,都是 User 类或是继承自 User 类的一个实例。

There are advangates and disadvantages to both typing systems. In strongly typed languages, the compiler can often provide you with through compile-time error checking, which is extremely helpful. Method inputs and outputs are also much more explicit in a strongly typed language.


As the same time, the explicit nature of strong typing can make it rigid. For example, dynamic methods such as whereEmailOrName that the Eloquent ORM offers would be impossible to implement in a strongly typed language like C#. Try to avoid heated discussions on which paradigm is better, and remember the advantages and disadvantages of each. It is not "wrong" to use the strong typing avaliable in PHP, nor is it wrong to use duck typing. What is wrong is exclusively using one or the other without considering the particular problem you are trying to solve.

与此同时,强类型的特性也使得程序僵化。比如 Eloquent ORM 中,类似 whereEmailOrName 的动态方法就不可能在 C# 这样的强类型语言里实现。我们不讨论强类型弱类型哪种更好,而是要记住他们分别的优劣之处。在 PHP 里面使用强类型标记不是错误,使用弱类型特性也不是错误。但是不加思索,不管实际情况去使用一种模式,这么固执的使用就是错的。

results matching ""

    No results matching ""