从内置类继承是否正确?

6 投票
6 回答
1236 浏览
提问于 2025-04-11 18:07

我想用一个Python程序以特定的方式解析Apache的access.log文件。虽然我对面向对象编程完全是个新手,但我想现在就开始尝试。

我打算创建一个类叫ApacheAccessLog,我现在能想到的就是它会有一个'readline'的方法。请问在这种情况下,从内置的file类继承是否合适,这样这个类的行为就像一个file类的实例一样,还是说这样做不太好?有什么更好的方法吗?

6 个回答

1

从内置类继承是完全可以的。在这种情况下,我觉得你的理解是正确的。
日志“是一个”文件,这说明继承是可以的。

一般规则。
狗“是一个”动物,所以可以从动物类继承。
主人“有一个”动物,所以不需要从动物类继承。

6

我之前是做Java的,但我觉得这些原则在Python中也适用。一般来说,你绝对不要去继承一个你不理解或无法控制的类,除非这个类是专门为继承设计的。如果是这样的话,它的文档里应该会清楚地说明。

这样做的原因是,继承可能会让你被你所继承的类的实现细节所束缚。

举个例子,来自Josh Bloch的书《Effective Java》。

假设我们想扩展ArrayList类,以便能够计算在其生命周期内添加的项目数量(不一定是当前包含的数量),我们可能会想写成这样。

public class CountingList extends ArrayList {
    int counter = 0;

    public void add(Object o) {
        counter++;
        super.add(0);
    }

    public void addAll(Collection c) {
        count += c.size();
        super.addAll(c);
    }

    // Etc.
}

现在这个扩展看起来可以准确地计算添加到列表中的元素数量,但实际上可能并不是这样。如果ArrayList通过遍历提供的Collection并对每个元素调用其接口方法addAll来实现addAll,那么我们就会把通过addAll方法添加的每个元素都计算两次。这样,我们的类的行为就依赖于ArrayList的实现细节了。

当然,这还不包括我们无法将其他List的实现与我们的CountingList类一起使用的缺点,以及上面提到的继承具体类的缺点。

我了解到,Python使用的调度机制与Java类似(如果不是完全相同的话),因此也会受到相同的限制。如果有人能提供一个Python的例子,那肯定会更有帮助。

15

在这种情况下,我会选择使用委托而不是继承。这意味着你的类应该把文件对象作为一个属性,并在它上面调用readline方法。你可以在日志记录器类的构造函数中传入一个文件对象。

这样做至少有两个原因:

  1. 委托可以减少耦合,比如你可以用任何其他实现了readline方法的对象来替代文件对象(这里的鸭子类型就派上用场了)。
  2. 如果你从文件继承,你的类的公共接口会变得不必要地宽泛。它会包含文件上定义的所有方法,即使这些方法在处理Apache日志时并没有意义。

撰写回答