将实例强制转换为具有额外数​​据成员的派生类

时间:2015-06-08 14:28:24

标签: python inheritance casting

这个问题与this非常相似,但我的派生类有额外的数据成员。考虑下面的两个类。我需要将Circle个对象的实例转换为ColoredCircle的实例。在我真实的,不太简单的应用程序中,我宁愿避免重新初始化数千个这些对象,确保我使用基本实例成员和诸如此类的东西正确调用派生类构造函数。

class Circle(object):
    def __init__(self, radius):
        self.radius = radius
    def area(self):
        return pi * self.radius**2
    def __str__(self):
        return 'Circle: %f' % self.radius

class ColoredCircle(Circle):
    def __init__(self, radius, color):
        super(ColoredCircle, self).__init__(radius)
        self.color = color
    def __str__(self):
        return 'ColoredCircle: %f %s' % (self.radius, self.color)
    def getColor(self):
        return self.color

如果我有一个Circle实例c,我可以将其__class__更改为ColoredCircle,一旦我也设置了c.color,那么一切似乎都起作用,好像我已经用ColoredCircle开始实例化了。

问题:

  1. 是否存在任何重大缺陷或其他原因,如果将基类的实例强制转换为派生类的实例,则执行以下操作会是一个坏主意?
  2. 有更好的方法吗?
  3. c = Circle(3)
    print c                     # Circle: 3.000000
    print c.area()              # 28.274333882308138
    c.__class__ = ColoredCircle
    print c.area()              # still works
    print c.getColor()          # AttributeError: 'ColoredCircle' object has no attribute 'color'
    c.color = 'blue'
    print c                     # ColoredCircle: 3.000000 blue
    

1 个答案:

答案 0 :(得分:3)

  

(1)是否存在任何重大缺陷或其他原因,如果将基类的实例强制转换为派生类的实例,则执行以下操作会是一个坏主意?

这是一个肮脏的脏兮兮的黑客,并侵犯了这个世界上所有善良和神圣的东西。小猫将在群众中灭亡。

这是对封装的公然违反。它只适用于派生类的深入了解。当你可以使用构造函数轻松创建一个干净的对象时,为什么要以脏的方式重写对象的DNA。

如果您完全了解目标对象的所有细节100%,那么确定,这是有效的,但这是一个非常脏的黑客。如果这是一次性校正或其他什么,你可能可以逃脱它,否则它将成为维护的噩梦,好像某天某些东西在目标类中发生了变化,你将不得不更新黑客。

  

(2)有更好的方法吗?

是的,使用构造函数创建不同类型的对象。现在还不清楚为什么你不愿意走这条明显的道路。