Python ondersteunt drie soorten methoden in klassedefinities: instantiemethoden, klassenmethoden en statische methoden. Ze verschillen in de manier van aanroepen en toegang tot de gegevens van de klasse en de instantie.
Geschiedenis:
Oorspronkelijk waren klassenmethoden (die met "self") de enige type gedrag, implicerend dat methoden altijd gedrag aanroepen of gegevens van een specifiek object lezen/wijzigen. Later kwamen klassenmethoden (met "cls") naar Python, die gedrag voor de hele klasse bieden (bijvoorbeeld alternatieve constructeurs), en statische methoden, die op gewone functies lijken, maar gekoppeld zijn aan de klasse.
Probleem:
Soms is er algemene functionaliteit nodig voor alle instanties (statische methoden). Soms moet een bewerking "voor de hele klasse" toegankelijk zijn (bijvoorbeeld het creëren van een instantie). Als het type methode verkeerd wordt gedefinieerd, kunnen er bugs optreden (bijvoorbeeld per ongeluk proberen de klasse te wijzigen via een instantiemethode, of omgekeerd).
Oplossing:
Voorbeeldcode:
class MyClass: def instance_method(self): return f"Instantie: {self}" @classmethod def class_method(cls): return f"Klasse: {cls}" @staticmethod def static_method(): return "Dit is een statische methode" obj = MyClass() print(obj.instance_method()) # Instantie: <MyClass object...> print(MyClass.class_method()) # Klasse: <class 'MyClass'> print(MyClass.static_method())# Dit is een statische methode
Belangrijke kenmerken:
Kan een instantiemethode rechtstreeks via de klasse worden aangeroepen?
Ja, maar het is nodig om het object expliciet door te geven:
MyClass.instance_method(obj)
wat zelden gepast is.
Gedrag van statische methoden bij overerving: kunnen ze worden overschreven?
Ja, je kunt een staticmethod in de dochterklasse met dezelfde naam declareren, en deze zal worden aangeroepen bij toegang vanuit de afgeleide klasse.
Waarom worden klassenmethoden gebruikt als je altijd statische methoden met cls als parameter kunt gebruiken?
cls is niet gewoon de eerste parameter: in classmethod plaatst Python automatisch de bijbehorende klasse als cls, zelfs als de aanroep vanuit de afgeleide klasse gebeurt. Dit maakt het mogelijk om een alternatieve hiërarchie van constructeurs te creëren zonder strikte binding aan de ouderklasse.
Voorbeeld:
class Base: @classmethod def make(cls): return cls() class Child(Base): pass Child.make() # retourneert Child, niet Base
In een project werden gewone methoden gebruikt voor het maken van alternatieve instanties (bijvoorbeeld, create_from_json). Hierdoor gaf de methode bij overerving altijd het object van de basisklasse terug, en niet van de afgeleide.
Voordelen:
Nadelen:
Er werden classmethod-fabrieken geïmplementeerd die instanties van de huidige klasse retourneren (cls()), zelfs als ze vanuit de afgeleide worden aangeroepen.
Voordelen:
Nadelen: