从内置类继承是否正确?
我想用一个Python程序以特定的方式解析Apache的access.log文件。虽然我对面向对象编程完全是个新手,但我想现在就开始尝试。
我打算创建一个类叫ApacheAccessLog,我现在能想到的就是它会有一个'readline'的方法。请问在这种情况下,从内置的file类继承是否合适,这样这个类的行为就像一个file类的实例一样,还是说这样做不太好?有什么更好的方法吗?
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的例子,那肯定会更有帮助。
在这种情况下,我会选择使用委托而不是继承。这意味着你的类应该把文件对象作为一个属性,并在它上面调用readline
方法。你可以在日志记录器类的构造函数中传入一个文件对象。
这样做至少有两个原因:
- 委托可以减少耦合,比如你可以用任何其他实现了
readline
方法的对象来替代文件对象(这里的鸭子类型就派上用场了)。 - 如果你从文件继承,你的类的公共接口会变得不必要地宽泛。它会包含文件上定义的所有方法,即使这些方法在处理Apache日志时并没有意义。