我知道它已被覆盖过,但我只是没有得到它......
我想创建一个用文件名调用的类,但是,根据文件名的扩展名,它会变换为几个子类中的一个。它认为它是一个工厂模式,我在使用静态方法之前就已经这样做了,但我现在正在尝试使用基类的常见实例来完成它。这可能吗?
>>> foo = FileClass('foo.txt')
>>> type(foo)
<type 'TextFileClass'>
>>> foo = FileClass('foo.rtf')
>>> type(foo)
<type 'RTFFileClass'>
这不是实际产量,而是我希望实现的目标。我正在尝试疯狂的东西,必须远离赛道。目前我已经在__new__
中实施了FileClass
例程,但似乎不对。似乎有很多方法可以做到这一点?什么是正确的?
答案 0 :(得分:4)
为什么不使用工厂功能?
class BaseFile(object):
"""Inherit these common methods and properties"""
def __init__(self, fname):
self.fname = fname
def is_pretty(self):
NotImplemented
class TextFileClass(BaseFile):
def is_pretty(self):
return False
class RTFFileClass(BaseFile):
def is_pretty(self):
return True
def createFileClass(fname):
if fname.endswith('.txt'):
return TextFileClass(fname)
elif fname.endswith('.rtf'):
return RTFFileClass(fname)
else:
raise Exception, 'unknown file format'
FileClass = createFileClass
产地:
>>> foo = FileClass('foo.txt')
>>> type(foo)
<class '__main__.TextFileClass'>
>>> foo = FileClass('foo.rtf')
>>> type(foo)
<class '__main__.RTFFileClass'>
答案 1 :(得分:2)
使用__new__
执行此操作的主要问题是,如果FileClass.__new__
调用TextFileClass
构造函数,TextFileClass
如何__new__
将实例转到cls
返回?
要解决此问题,我们可以测试__new__
中__new__
的内容,因此我们不会干扰子类“def __new__(cls, filename):
if cls is FileClass:
return cls._factory(filename)
return super(FileClass, cls).__new__(cls, filename)
:
FileClass('foo.txt')
当调用__init__
时,如果__new__
的实例是FileClass
,则Python会对TextFileClass.__new__('foo.txt')
返回的对象调用TextFileClass('foo.txt')
,因此我们必须使用@classmethod
def _factory(cls, filename):
if filename.endswith('.txt'):
return TextFileClass.__new__(filename)
elif filename.endswith('.rtf'):
return RTFFileClass.__new__(filename)
...
而不是{{1}}:
{{1}}
总而言之,以这种方式做事可能不值得。工厂功能或工厂方法更容易正确。
答案 2 :(得分:0)
如果FileClass
不能是工厂函数,则可以应用Handle/Body模式(或派生的Envelope/Letter模式)让FileClass
实例化实现类,将它保存在字段中并且代理方法调用它。消费者不会在变量类型中看到子类,但接口将存在,这是重要的事情。