I created an abstract class Animal
for simillar classes (Cat, Dog, Horse ...
) sharing simillar methods.
Also, I want to use the class Animal
as an indicator of their common attributes(id, name, weight, ...
) and their types as code below, but it looks so ugly to me.
from abc import ABC, abstractmethod
from typing import Optional
class Animal(ABC):
def __init__(self) -> None:
self.id: Optional(int) = None
self.name: Optional(str) = None
self.weight: Optional(float) = None
self.height: Optional(float) = None
self.age: Optional(int) = None
...
@abstractmethod
def cry(self) -> None:
pass
Should I type hint all attributes as Optional, since their values are not determined (so I initialized them with None
) in abstract class Animal
? Are there any better way to type-hint undetermined class attributes?
If the goal is to say that any subclass of Animal
should have the attributes id
, name
, etc., but not providing any defaults (which I assume is why you assigned them None
), then you can declare them using class attribute annotations:
class Animal(ABC):
id: int
name: str
weight: float
height: float
age: int
@abstractmethod
def cry(self) -> None:
....
Note that this will not provide you with guarantees that all subclasses must have these attributes. It's merely a hint to the programmer and the IDE & typechecker, and in most cases this will suffice.
If you wish to be certain, you can define them as abstract properties, although it would be quite verbose:
class Animal(ABC):
@property
@abstractmethod
def name(self) -> str:
...
# Subclasses can implement that as a simple class attribute...
class Cat(Animal):
name = "cat"
# ... or as a proper property.
class Dog(Animal):
@property
def name(self) -> str:
return f"{self.breed} dog"