Python 具有不同接口的派生类
以下代码:Python 具有不同接口的派生类,python,inheritance,adapter,Python,Inheritance,Adapter,以下代码: class Cache: def __init__(self): self._cache = [] def store(self, data): self._cache.append(data) def stats(self): print('We are caching {} elements'.format(len(self._cache))) class LegoCache(Cache):
class Cache:
def __init__(self):
self._cache = []
def store(self, data):
self._cache.append(data)
def stats(self):
print('We are caching {} elements'.format(len(self._cache)))
class LegoCache(Cache):
def store(self, weight, color):
Cache.store(self, (weight, color))
存在一个问题,store
方法没有实现基类的接口
如何改进此代码?我有以下想法:
- 不要从
缓存中派生,只要利用它
- 将基类中的
方法重命名为store
store\u base
class ZombieCache(Cache):
def store(self, dead_since, humans_eaten, can_be_saved=False):
Cache.store(self, dict(
dead_since=dead_since,
humans_eaten=humans_eaten,
can_be_saved=can_be_saved))
可以在基类中使用变量参数列表:
class Cache:
def __init__(self):
self._cache = []
def store(self, *args):
self._cache.append(args)
def stats(self):
print('We are caching {} elements'.format(len(self._cache)))
class LegoCache(Cache):
pass
# "overloading" store isn't needed
因此,不需要重载此方法或为特殊情况添加具有不同名称的方法:
cache = Cache()
legoCache = LegoCache()
cache.store(x)
legoCache.store(x, y)
另一种解决办法可能是授权:
class LegoCache(object):
def __init__(self):
self.cache = Cache()
def store(self, weight, color):
self.cache.store((weight, color))
# or just self.cache.store(weight, color) if you use the *args implementation
我会这样实施,
class Cache:
def __init__(self):
self._cache = []
def store(self, data):
self._cache.append(data)
def stats(self):
print('We are caching {} elements'.format(len(self._cache)))
class LegoData(object):
def __init__(self, weight, color):
self.weight = weight
self.color = color
class LegoCache(Cache):
pass
lego_cache = LegoCache()
lego_cache.store(LegoData(weight=10, color='Green'))
客户端将像这样访问它
class Cache:
def __init__(self):
self._cache = []
def store(self, data):
self._cache.append(data)
def stats(self):
print('We are caching {} elements'.format(len(self._cache)))
class LegoData(object):
def __init__(self, weight, color):
self.weight = weight
self.color = color
class LegoCache(Cache):
pass
lego_cache = LegoCache()
lego_cache.store(LegoData(weight=10, color='Green'))
这真的重要吗?@stephernauch,
PyCharm
不快乐,所以我不快乐。但说真的,这不是一种代码味道吗?我是一个大派克,但这里的范围是什么?除了要求调用方存储以显式传递元组外:store((weight,color))
,或者将基存储更改为store(*args)
,那么args始终是元组。@Stephenauch,这些都不吸引我,因为派生类的全部目的是为调用方提供一个简化的接口,为了使一个接口适应另一个接口。很公平……Nononono,基类有一个定义良好的实现:它接受一个数据参数,它可以是任何东西。派生类为特定情况提供了一个更方便的接口。@dangonfast:事实上,这并不好。(Un-)幸运的是,Python不支持方法重载。如果您不喜欢这样,则必须为每个项类型声明特殊方法。但是请注意,您也可以在LegoCache
中调用store()
。但是你应该考虑使用委托而不是继承。@ DangOnFAST:我增加了一个委派例子。谢谢!对我来说,这似乎是最干净的解决办法。不幸的是,这个实现隐藏了一个事实,即这是从缓存派生出来的,但是正如您所提到的,如果没有方法重载,就不可能实现这一点。LegoCache
的全部要点是提供一个简单、可用的界面,以便用户可以轻松地使用它。此实现只提供一个基本的缓存
,用户完全负责实例化数据。因此,LegoCache
是多余的。另一方面,LegoData
确实可以用作缓存的数据元素,但这是一个(ortogonal)实现细节,而不是我的问题。