如何理解面向对象设计

4

面向对象设计是一个非常棒的概念,但我在如何理解它的大部分方面上感到困惑。我认为好的面向对象设计的关键在于如何看待它。我通常这样看待面向对象:

类是现实世界中的实体或对象

实例字段是实体的属性('有 A')

方法就像动作、动词,是实体的能力

接口就像你可以赋予对象的能力。它也可以是“是 A 或可以做”关系,其实现并不是铁板一块。超人是克里普顿人,作为克里普顿人具备一些特殊能力,比如飞行、冰冻呼吸等。超人的飞行方式与绿灯侠、孙悟空和蝙蝠侠等人不同,因此如果你正在创建一个虚构宇宙,将飞行作为接口可能是个不错的主意。

public class SuperMan extends Man implements Kryptonian{}

public interface Kryptonian extends Flight, FreezeBreath{
    public void fly();
    public void coolBreath();
}

当你把泛型应用到代码中时,问题就随之而来了。因为类型参数在类/接口和类型之间创建了某种约定。

public interface Flight<T>{
     public void fly(T t);
}

在这个例子中,Flight与T耦合,T可以是一个超级英雄、一只鸟或者任何能飞的东西。但这真的是我应该想象的吗?因为这似乎和普通接口做的事情一样?虽然,参数化接口仍然是一个接口,但与类型T的耦合确实让我感到困扰。此外,当你在参数类型上加上有界限制时,事情也变得复杂了起来。
public class Pidgey<T extends Bird> implements Flight<T>{}

您能够将T与哪个真实的具体对象进行关联?上面的例子是相当错误的,虽然使用类参数来限制Flight类型可能是一个好的设计,因为Flight仍然足够独立,其他类可以在没有任何限制的情况下使用它。但是这个例子本身是错误的。Pidgey是一只会飞的鸟,但T可以是任何东西,它可以是另一个对象或能力。问题是它的含义是什么,为什么要把T放在那里?有哪些现实世界的例子呢?

当谈到集合时很容易理解,因为集合就像容器。您可以创建各种不同类型的容器来容纳不同类型的对象。

public class WaterBottle<T extends Liquid> implements UniqueCap{}

但我看到泛型不仅被用于类似容器的对象上,如何设计这样的对象,他们考虑了什么?


4
超人的能力在技术上取决于他所处的环境。 - Dave Newton
4
为了符合“对象代表实际事物”的思想(我认为这并不是面向对象编程的真正含义),您可以始终使用类似public interface Flock<T extends Bird>的群体接口,其中群体是一组鸟 - 虽然这仍然是一个容器(本质上是)。 - Jared
2
这个问题太宽泛而且太分散了。按照目前的陈述方式,没有简洁地回答这个问题的方法。尝试将其拆分为更小的问题,每个问题都有一个具体的焦点。 - scottb
1
在你的第一个例子中,我会说 T 可以代表用于飞行的燃料或能源类型。 - Drazen Bjelovuk
1
是的,将其实现为通用类型只是为了更大的灵活性,以考虑燃料类型不总是相同的情况,假设您的燃料由其自己的类表示具有特定属性。 - Drazen Bjelovuk
显示剩余4条评论
2个回答

4
你对面向对象编程中的各种特性做出的比喻是有道理的。泛型在谈论集合/容器/哈希映射时确实最有意义。但它们也可以在其他地方使用。例如,如果银行想要处理多种货币的纸币,他们可以写一个名叫moneyProcessor的公共类。
然而,泛型不是必需的。在你的Flight接口的上下文中,没有太多使用泛型的理由。这也引出了另一个观点:
仅因为其他人采用一种方式并不意味着你必须也这样做。面向对象编程非常灵活,这是有原因的。永远不止一种正确的方法。如果一个方法以Object作为参数,那也没关系。只要确保你以后可以读懂它。 :)
编辑:确保别人也能读懂它。

0

在处理泛型时,使用T是惯例。这使得代码易读,因为其他人阅读您的代码时立即知道您正在引用泛型而不是特定的内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接