Saya tahu metode virtual dari PHP atau Java.
Bagaimana mereka bisa diimplementasikan dengan Python?
Atau haruskah saya mendefinisikan metode kosong dalam kelas abstrak dan menimpanya?
sumber
Saya tahu metode virtual dari PHP atau Java.
Bagaimana mereka bisa diimplementasikan dengan Python?
Atau haruskah saya mendefinisikan metode kosong dalam kelas abstrak dan menimpanya?
Tentu, dan Anda bahkan tidak perlu mendefinisikan metode di kelas dasar. Dalam Python, metode lebih baik daripada virtual - metode ini benar-benar dinamis, karena pengetikan dengan Python adalah pengetikan bebek .
class Dog:
def say(self):
print "hau"
class Cat:
def say(self):
print "meow"
pet = Dog()
pet.say() # prints "hau"
another_pet = Cat()
another_pet.say() # prints "meow"
my_pets = [pet, another_pet]
for a_pet in my_pets:
a_pet.say()
Cat
dan Dog
di Python bahkan tidak harus diturunkan dari kelas dasar yang sama untuk mengizinkan perilaku ini - Anda mendapatkannya secara gratis. Meskipun demikian, beberapa programmer lebih memilih untuk mendefinisikan hierarki kelas mereka dengan cara yang lebih kaku untuk mendokumentasikannya dengan lebih baik dan menerapkan beberapa ketelitian pengetikan. Ini juga dimungkinkan - lihat misalnya abc
modul standar .
raise NotImplementedError()
Ini adalah pengecualian yang disarankan untuk dimunculkan pada "metode virtual murni" dari kelas dasar "abstrak" yang tidak mengimplementasikan metode.
https://docs.python.org/3.5/library/exceptions.html#NotImplementedError mengatakan:
Seperti yang dikatakan orang lain, ini sebagian besar adalah konvensi dokumentasi dan tidak diperlukan, tetapi dengan cara ini Anda mendapatkan pengecualian yang lebih berarti daripada kesalahan atribut yang hilang.
Misalnya:
class Base(object): def virtualMethod(self): raise NotImplementedError() def usesVirtualMethod(self): return self.virtualMethod() + 1 class Derived(Base): def virtualMethod(self): return 1 print Derived().usesVirtualMethod() Base().usesVirtualMethod()
memberikan:
2 Traceback (most recent call last): File "./a.py", line 13, in <module> Base().usesVirtualMethod() File "./a.py", line 6, in usesVirtualMethod return self.virtualMethod() + 1 File "./a.py", line 4, in virtualMethod raise NotImplementedError() NotImplementedError
Terkait: Apakah mungkin membuat kelas abstrak dengan Python?
sumber
Metode Python selalu virtual.
sumber
Sebenarnya, di versi 2.6 python menyediakan sesuatu yang disebut kelas dasar abstrak dan Anda dapat secara eksplisit mengatur metode virtual seperti ini:
from abc import ABCMeta from abc import abstractmethod ... class C: __metaclass__ = ABCMeta @abstractmethod def my_abstract_method(self, ...):
Ia bekerja dengan sangat baik, asalkan kelas tersebut tidak mewarisi dari kelas yang sudah menggunakan metaclass.
sumber: http://docs.python.org/2/library/abc.html
sumber
seperti yang dikatakan Ignacio. Entah bagaimana, warisan kelas mungkin merupakan pendekatan yang lebih baik untuk menerapkan apa yang Anda inginkan.
class Animal: def __init__(self,name,legs): self.name = name self.legs = legs def getLegs(self): return "{0} has {1} legs".format(self.name, self.legs) def says(self): return "I am an unknown animal" class Dog(Animal): # <Dog inherits from Animal here (all methods as well) def says(self): # <Called instead of Animal says method return "I am a dog named {0}".format(self.name) def somethingOnlyADogCanDo(self): return "be loyal" formless = Animal("Animal", 0) rover = Dog("Rover", 4) #<calls initialization method from animal print(formless.says()) # <calls animal say method print(rover.says()) #<calls Dog says method print(rover.getLegs()) #<calls getLegs method from animal class
Hasilnya harus:
I am an unknown animal I am a dog named Rover Rover has 4 legs
sumber
Sesuatu seperti metode virtual di C ++ (implementasi metode panggilan dari kelas turunan melalui referensi atau penunjuk ke kelas dasar) tidak masuk akal di Python, karena Python tidak memiliki pengetikan. (Saya tidak tahu bagaimana metode virtual bekerja di Java dan PHP.)
Tetapi jika yang Anda maksud dengan "virtual" adalah memanggil implementasi paling bawah dalam hierarki pewarisan, maka itulah yang selalu Anda dapatkan dengan Python, seperti yang ditunjukkan beberapa jawaban.
Hampir selalu ...
Seperti yang ditunjukkan dplamp, tidak semua metode dalam Python berperilaku seperti itu. Metode Dunder tidak. Dan menurut saya itu adalah fitur yang tidak begitu terkenal.
Pertimbangkan contoh buatan ini
class A: def prop_a(self): return 1 def prop_b(self): return 10 * self.prop_a() class B(A): def prop_a(self): return 2
Sekarang
>>> B().prop_b() 20 >>> A().prob_b() 10
Namun, pertimbangkan yang satu ini
class A: def __prop_a(self): return 1 def prop_b(self): return 10 * self.__prop_a() class B(A): def __prop_a(self): return 2
Sekarang
>>> B().prop_b() 10 >>> A().prob_b() 10
Satu-satunya hal yang kami
prop_a()
ubah adalah membuat metode yang konyol.Masalah dengan perilaku pertama adalah Anda tidak dapat mengubah perilaku
prop_a()
di kelas turunan tanpa memengaruhi perilakuprop_b()
. Ini sangat bagus bicara oleh Raymond Hettinger memberikan contoh untuk kasus penggunaan di mana ini tidak nyaman.sumber