Donc, voici un problème:
Je veux définir une classe abstraite, disons De plus, je veux être capable de créer une sous-classe abstraite, disons Je ne veux pas cependant faire la classe ( Alors, je veux quelque chose Comme ça: p> ci-dessous j'ai une solution possible.
Y a-t-il des inconvénients que je néglige-t-il? Meilleure solution? P> merci! P> p> abstractha code>, qui ne nécessite pas de sous-classes pour mettre en œuvre de ses méthodes, mais plutôt pour étendre ses fonctionnalités. En termes de java qui serait une classe d'interface. P> li>
abstractb code>, du
abstractta code> avec les mêmes propriétés, mais quelques méthodes redéfinir ou Extension des méthodes de classe de base. P> li>
ol>
abstractha code>) abstrait E.g. via la vérification du nom de la classe dans
__ init __ code > ou
, car cela nécessiterait une sous-classe abstraite ( __ nouveau __ code>
abstractb code>) pour redéfinir cette méthode avec sa fonctionnalité principale, c'est-à-dire la construction ou l'initialisation d'une nouvelle instance. Ou appeler
super () .__ init __ (...) code> que je préférerais éviter également (peut-être que je me trompe ici). P>
3 Réponses :
Voici une solution possible:
class AbstractA: _is_abstract = True def __init__(self): if self._is_abstract: raise RuntimeError("Abstract class instantiation.") # do initialization stuff def __init_subclass__(self): # is called every time class is subclassed self._is_abstract = False # thus makes sure abstract check fails on a subclass class AbstractMixin: def __init_subclass__(self): self._is_abstract = True class AbstractB(AbstractMixin, AbstractA): # AbstractMixin takes precendence on MRO, # inherit __init__ # so the class abstract check returns True. def __init_subclass__(self): self._is_abstract = False class A(AbstractA): pass class B(AbstractB): pass AbstractA() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 5, in __init__ RuntimeError: Abstract class instantiation. AbstractB() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 5, in __init__ RuntimeError: Abstract class instantiation. A() <__main__.A object at 0x7f0bba5112e8> B() <__main__.B object at 0x7f0bba511438>
>>> B() B <__main__.B object at 0x7f8c816a58d0> >>>
J'ai spécifiquement mentionné cette approche et pourquoi je ne veux pas l'utiliser dans une question.
Dans Python, vous mettriez probablement en œuvre les classes de base "abstraites" comme mix-ins. Il n'y a rien de spécial que vous devez faire; Par convention, vous ajouteriez mixin code> au nom pour indiquer qu'il n'est pas censé être instancié directement, mais simplement utilisé comme classe de base pour d'autres classes.
class AMixin:
def __init__(self):
# do initialization stuff
def very_common_method(self, ...):
# do very common stuff
class BMixin(AMixin):
# do not duplicate initialization stuff here, inherit instead
def less_common_method(self, ...):
# do less common stuff
class AX(AMixin):
def specific_method_1(self, ...):
class BX(BMixin):
def specific_method_2(self, ...):
class Foo:
...
class Bar(Foo, BMixin):
...
mixin code> dans le nom n'indique pas qu'il devrait simplement être "utilisé comme une classe de base", cela doit plutôt l'indiquer, il doit être utilisé comme mixin, c'est-à-dire secondaire, tertiaire, etc. Parent, fournissant des morceau de fonctionnalité.
Devrait
Class Ax (Abstractha): Pass Code> Soyez légal? Quel serait le point de refusement instanciation directe de
abstractha code> mais permettant l'instanciation de
hache code>?
@cheppner, bonne question. Je dois accepter que cette exigence soit plus une préférence que la nécessité. La raison pour laquelle je veux avoir une classe abstraite est que l'instanciation de cette classe mère ne fait aucun sens. Comme si dans la mise en œuvre d'animaux virtuels, il n'a pas de sens d'instancier des animaux ou des mammifères. Au lieu de cela, il faut instancier des espèces plus détaillées. Je tiens donc à rendre plus difficile à abuser de la classe uniquement à dessein de définir des propriétés communes. Quant à la partie du poing, il n'est pas assez difficile d'interdire complètement la mus mustueuse, mais suffisamment pour l'empêcher d'accident. Un peu comme _private_identifiers.