I came across this SESE page: What is a proper use of downcasting? (for C#) -- and it talks about when to downcast, and the possible downsides to it.
In Python sub classes are slightly different
Example:
Suppose I have the following abstract
class:
from abc import ABCMeta
from abc import abstractmethod
class Weapon(metaclass=ABCMeta):
def __init__(self, name, damage):
self.name = name
self.damage = damage
@abstractmethod
def prepare(self):
pass
@abstractmethod
def attack(self):
pass
@abstractmethod
def cleanup(self):
pass
def __str__(self):
return "Name: {} Damage: {}".format(self.name, self.damage)
and Subclass:
from Weapon import Weapon
class ChargeGun(Weapon):
def __init__(self, name, damage):
super().__init__(name, damage)
def prepare(self):
print("Aiming my Gun");
def attack(self):
print("Shooting")
def cleanup(self):
print("Lowering gun, and turning off laser sight")
def charge(self):
print("Charging Gun. Please hold..(elevator music playing)")
In my subclass ChargeGun
, I have the def charge(self):
method, and I can declare in the main a ChargeGun
object and use it, like this:
cg = ChargeGun("Standard ChargeGun",5)
cg.prepare()
cg.charge()
If I were to introduce Sword
as a Weapon
subclass, the charge(self):
would not be implemented, and Sword
isn't even aware of it. In Python, there isn't a need to downcast or use a design pattern.
Python isn't Java/C#.
Questions
How should you be thinking when creating sub classes in languages like Python? Should we be thinking from an abstract point of view, and refactor our code?
Example:
def charge(self):
could be seen as a way to prepare aChargeGun
so we can remove it. If I had a silencer, that's a a component of a Gun, so maybe it might make sense to have anabstract
WeaponComponent
class, a silencer and laser sight could be objects of that class and each would override thedef prepare(self):
method. A Sword could have a gem or stone that gives it extra strike ability, etc.
That's just one way of thinking, I'm not saying it's the best way to refactor it.
- Is it okay to take advantage of Python's ability to use the methods of a subclass directly?
if isinstance(weapon, ChargeGun): weapon.charge()
, I feel like that answers your question.ChargeGun
, if not directly? Or are you saying don't have thecharge(self):
method?