class ThirdPartyA(object):
def __init__(self):
...
def ...():
...
-------------------
from xxx import ThirdPartyA
class ThirdPartyB(object):
def a(self):
...
#call to ThirdPartyA
....
def b(self):
...
#call to ThirdPartyA
...
def c(self):
...
#call to ThirdPartyA
...
-----------------------------------
from xxx import ThirdPartyA
class MyCodeA(ThirdPartyA):
def __init__(self):
# overriding code
当覆盖A类的__init__
方法时,我如何指示B类应该在其所有方法中调用MyCodeA而不是ThirdPartyA?
真正的代码在这里:
CLass Geoposition: ThirdPartyA
Class GeopositionField: ThirdPartyB
我对类Geoposition的覆盖,因此返回最多5位小数:
class AccuracyGeoposition(Geoposition):
def __init__(self, latitude, longitude):
if isinstance(latitude, float) or isinstance(latitude, int):
latitude = '{0:.5f}'.format(latitude)
if isinstance(longitude, float) or isinstance(longitude, int):
longitude = '{0:.5f}'.format(longitude)
self.latitude = Decimal(latitude)
self.longitude = Decimal(longitude)
答案 0 :(得分:1)
假设您的真实代码就像您的示例一样 - 也就是说,B
的每个方法都会创建一个新的A
实例,只是为了调用它上面的方法并将其丢弃,这是一个非常奇怪的设计,但如果它对你的用例有意义,你可以使它工作。
这里的关键是类是第一类对象。而不是硬编码A
,将您想要的类存储为B
实例的成员,如下所示:
class B(object):
def __init__(self, aclass=A):
self.aclass = aclass
def a(self):
self.aclass().a()
现在,您只需使用子类创建一个B
实例:
b = B(OverriddenA)
您编辑的版本有一个不同的奇怪的东西:每次调用方法时都不会构建一个新的A
实例,而是在A
上调用类方法本身。同样,这可能不是你想要的 - 但是,如果是,你可以这样做:
class B(object):
def __init__(self, aclass=A):
self.aclass = aclass
def a(self):
self.aclass.a()
然而,你更有可能不想要其中任何一个。您希望在构建时采用A
实例,存储它并重复使用它。像这样:
class B(object):
def __init__(self, ainstance):
self.ainstance = ainstance
def a(self):
self.ainstance.a()
b1 = B(A())
b2 = B(OverriddenA())
如果这一切看起来很抽象而且难以理解......那就是因为我们使用了无意义的名称,如A
,B
和OverriddenA
。如果你告诉我们你正在考虑的实际类型,或者只是机械地插入这些类型,它应该更有意义。
例如:
class Vehicle(object):
def move(self):
print('I am a vehicle, and I am moving')
class Operator(object):
def __init__(self, vehicle):
self.vehicle = vehicle
def move(self):
print('I am moving my vehicle')
self.vehicle.move()
class Car(object):
def move(self):
print('I am a car, and I am driving')
driver = Operator(Car())
driver.move()
答案 1 :(得分:1)
从您更新的代码中,我认为您尝试要做的是更改GeopositionField. to_python()
,以便它返回AccuracyGeoposition
值而不是Geoposition
值。
没有办法直接这样做; GeopositionField
中的代码明确表示要构建Geoposition
,这就是发生的事情。
最干净的解决方案是将GeopositionField
子类化,因此您可以包装该方法:
class AccuracyGeopositionField(GeopositionField):
def topython(self, value):
geo = super(AccuracyGeopositionField, self).topython(value)
return AccuracyGeoposition(geo.latitude, geo.longitude)
如果创建Geoposition
然后重新包装AccuracyGeoposition
中的值是不够的(因为准确性已经丢失),您可以在调用super方法之前预处理事情同样/相反。例如,如果它处理list
的方式是不可接受的(我意识到这里不是真的,但它只是一个简单的例子),但是其他一切你可以让它做它的事情并包装结果,你可以这样做:
class AccuracyGeopositionField(GeopositionField):
def topython(self, value):
if isinstance(value, list):
return AccuracyGeoposition(value[0], value[1])
geo = super(AccuracyGeopositionField, self).topython(value)
return AccuracyGeoposition(geo.latitude, geo.longitude)
如果最糟糕的情况发生,您可能必须重新实现整个方法(可能通过复制,粘贴和修改其代码),但希望很少出现。
有一些黑客替代品。例如,您可以将模块monkeypatch以全局替换Geoposition
类与您的AccuracyGeoposition
类但是,虽然这可能会预先保存一些工作,但当您'时,您几乎肯定会对它感到不满意。稍后重新调试。专为面向方面编程而设计的系统(基本上是受控制的monkeypatching)非常棒,但是试图将其塞进旨在抵制它的系统中会让你头疼。