虚拟课堂:做对了吗?

12 投票
4 回答
16316 浏览
提问于 2025-04-16 00:11

我一直在阅读关于类继承、抽象基类甚至是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

撰写回答