虚拟课堂:做对了吗?
我一直在阅读关于类继承、抽象基类甚至是Python接口的文档。但似乎没有找到完全符合我需求的内容。也就是说,我想要一个简单的方法来构建虚拟类。当这个虚拟类被调用时,我希望它能够根据传入的参数实例化一个更具体的类,并把这个具体类返回给调用的函数。目前,我的做法是把对虚拟类的调用转发到底层类。
我的想法是这样的:
class Shape:
def __init__(self, description):
if description == "It's flat": self.underlying_class = Line(description)
elif description == "It's spiky": self.underlying_class = Triangle(description)
elif description == "It's big": self.underlying_class = Rectangle(description)
def number_of_edges(self, parameters):
return self.underlying_class(parameters)
class Line:
def __init__(self, description):
self.desc = description
def number_of_edges(self, parameters):
return 1
class Triangle:
def __init__(self, description):
self.desc = description
def number_of_edges(self, parameters):
return 3
class Rectangle:
def __init__(self, description):
self.desc = description
def number_of_edges(self, parameters):
return 4
shape_dont_know_what_it_is = Shape("It's big")
shape_dont_know_what_it_is.number_of_edges(parameters)
不过,我的转发方式并不理想,因为只有对number_of_edges()这个函数的调用被转发了。把类似的代码加到Shape类里似乎也没什么效果:
def __getattr__(self, *args):
return underlying_class.__getattr__(*args)
我哪里做错了呢?这个想法是不是实现得不好?任何帮助都非常感谢。
4 个回答
1
Python本身并不支持虚拟类,你需要自己去实现它们(这应该是可行的,因为Python的反射能力足够强大,可以让你做到这一点)。
不过,如果你需要虚拟类,那为什么不直接使用一些支持虚拟类的编程语言呢,比如Beta、gBeta或者Newspeak?(顺便问一下,还有其他语言吗?)
不过在这个特定的情况下,我并不觉得虚拟类会让你的解决方案变得更简单,至少在你给出的例子中是这样。也许你可以详细说明一下你为什么觉得需要虚拟类?
别误会,我喜欢虚拟类,但只有三种语言实现过它们,而这三种语言中只有一种还在使用,而且这三种语言实际上没有人用,这点还是挺值得注意的……
19
我同意TooAngel__new__方法。
class Shape(object):
def __new__(cls, *args, **kwargs):
if cls is Shape: # <-- required because Line's
description, args = args[0], args[1:] # __new__ method is the
if description == "It's flat": # same as Shape's
new_cls = Line
else:
raise ValueError("Invalid description: {}.".format(description))
else:
new_cls = cls
return super(Shape, cls).__new__(new_cls, *args, **kwargs)
def number_of_edges(self):
return "A shape can have many edges…"
class Line(Shape):
def number_of_edges(self):
return 1
class SomeShape(Shape):
pass
>>> l1 = Shape("It's flat")
>>> l1.number_of_edges()
1
>>> l2 = Line()
>>> l2.number_of_edges()
1
>>> u = SomeShape()
>>> u.number_of_edges()
'A shape can have many edges…'
>>> s = Shape("Hexagon")
ValueError: Invalid description: Hexagon.
17
我更喜欢用工厂模式来实现这个:
def factory(description):
if description == "It's flat": return Line(description)
elif description == "It's spiky": return Triangle(description)
elif description == "It's big": return Rectangle(description)
或者:
def factory(description):
classDict = {"It's flat":Line("It's flat"), "It's spiky":Triangle("It's spiky"), "It's big":Rectangle("It's big")}
return classDict[description]
并且从形状类(Shape)继承这些类
class Line(Shape):
def __init__(self, description):
self.desc = description
def number_of_edges(self, parameters):
return 1