parent.py
:
class A(object):
def methodA(self):
print("in methodA")
child.py
:
from parent import A
class B(A):
def methodb(self):
print("am in methodb")
Есть ли methodb()
вызвать methodb()
в parent.py
?
parent.py
:
class A(object):
def methodA(self):
print("in methodA")
child.py
:
from parent import A
class B(A):
def methodb(self):
print("am in methodb")
Есть ли methodb()
вызвать methodb()
в parent.py
?
Выполнение этого имеет смысл только в том случае, если A
является абстрактным базовым классом, что означает, что A
предназначен только для использования в качестве базы для других классов, а не для непосредственного создания. Если бы это было так, вы бы определили methodB
в классе A, но не допустили его:
class A(object):
def methodA(self):
print("in methodA")
def methodB(self):
raise NotImplementedError("Must override methodB")
from parent import A
class B(A):
def methodB(self):
print("am in methodB")
Это не обязательно. Если вы не объявляете methodB
нигде в A
и не создаете экземпляр B
, вы все равно сможете вызвать methodB
из тела methodA
, но это плохая практика; неясно, откуда предполагается methodA
, или что дочерние классы должны переопределить его.
Если вы хотите быть более формальным, вы можете использовать модуль Python abc
для объявления A как абстрактного базового класса.
from abc import ABCMeta, abstractmethod
class A(object):
__metaclass__ = ABCMeta
def methodA(self):
print("in methodA")
@abstractmethod
def methodB(self):
raise NotImplementedError("Must override methodB")
Использование этого фактически не позволит вам создавать экземпляр A
или любой класс, который наследует от A
без переопределения methodB
. Например, если B выглядел так:
class B(A):
pass
У вас возникнет ошибка при попытке его создания:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class B with abstract methods methodB
То же самое произойдет, если вы попытаетесь создать экземпляр A
.
Вы можете сделать что-то вроде этого:
class A():
def foo(self):
self.testb()
class B(A):
def testb(self):
print 'lol, it works'
b = B()
b.foo()
Обратите внимание, что на самом деле нет вызова от родителя, есть только вызов функции foo
из экземпляра дочернего класса, этот экземпляр унаследовал foo
от родителя, т.е. это невозможно:
a=A()
a.foo()
будет производить: AttributeError: A instance has no attribute 'testb'
потому что
>>> dir(A)
['__doc__', '__module__', 'foo']
>>> dir(B)
['__doc__', '__module__', 'foo', 'testb']
Что я хотел показать, что вы можете создать экземпляр дочернего класса, и он будет иметь все методы и параметры как из родителя, так и из его собственных классов.
Вы можете использовать эту функцию в любом месте, пока она была прикреплена к объекту, который, по-видимому, относится к вашему образцу. Если у вас есть объект B
, вы можете использовать его функцию methodb()
из абсолютно где угодно.
parent.py:
class A(object):
def methoda(self):
print("in methoda")
def aFoo(obj):
obj.methodb()
child.py
from parent import A
class B(A):
def methodb(self):
print("am in methodb")
Вы можете увидеть, как это работает после импорта:
>>> from parent import aFoo
>>> from child import B
>>> obj = B()
>>> aFoo(obj)
am in methodb
Конечно, вы не сможете создать новый объект B
изнутри parent.py
, но вы все равно сможете использовать его методы, если он каким-то образом перешел к функции в parent.py
.
Есть три подхода/способа сделать это! но я настоятельно рекомендую использовать подход № 3, потому что композиция/разделение имеет определенные преимущества с точки зрения шаблона проектирования. (GOF)
## approach 1 inheritance
class A():
def methodA(self):
print("in methodA")
def call_mehtodB(self):
self.methodb()
class B(A):
def methodb(self):
print("am in methodb")
b=B()
b.call_mehtodB()
## approach 2 using abstract method still class highly coupled
from abc import ABC, abstractmethod
class A(ABC):
def methodA(self):
print("in methodA")
@abstractmethod
def methodb(self):
pass
class B(A):
def methodb(self):
print("am in methodb")
b=B()
b.methodb()
#approach 3 the recommended way ! Composition
class A():
def __init__(self, message):
self.message=message
def methodA(self):
print(self.message)
class B():
def __init__(self,messageB, messageA):
self.message=messageB
self.a=A(messageA)
def methodb(self):
print(self.message)
def methodA(self):
print(self.a.message)
b=B("am in methodb", "am in methodA")
b.methodb()
b.methodA()
Нет, вы не должны пытаться вызывать метод в родительском классе, когда он определен в дочернем классе. Хотя вы можете использовать обходной путь, чтобы позволить это, это плохая практика. Подумайте, нужно ли всем детям использовать этот метод и перенести его в родительский класс. Если метод нужен не всем детям, оставьте его в классе детей.