We will not only use program fragments, but also proceed with learning toward the implementation of programs that combine them.
Thanks to the extensive library and commentary, I managed to realize the little idea that I wanted to do and that I wanted to do. On the other hand, if you try to combine them to make one program, the whole thing will be messed up and you will not be able to handle it.
Therefore, here we will organize what we have learned about the class and summarize various matters for the purpose of creating a "program that can be expanded and maintained by ourselves". As a programmer who is still a beginner, advice is welcome.
Naming is important in the program. If you give it an appropriate name, it will hinder your understanding and recognition. Therefore, the degree of abstraction must be determined according to the situation in order to get a firm grasp of what is going on.
If you search for "Python class abstraction", most of the information is about how to use metaclasses. This is a part that was unexpectedly difficult to understand.
As an example, imagine the situation of making a classic Western fantasy role-playing game. What kind of name should we give when creating a class that deals with one character, John, a villager?
First of all, as a premise, various things in the world belong to multiple groups at the same time. Of course John is no exception.
There are a number of names that John can give, just for a quick glance. An Object that is all objects (grounds, trees, buildings, characters, etc.) that exist in the game. Creature is a living thing among living things and inanimate objects. Humanoid, a humanoid creature that may include elves and dwarves as well as ordinary people. As a result of endlessly tracing among the humanoid creatures, we arrive at John, a villager.
When it comes to "Would you like to make Creature for living things for the time being?", I think the implementation will be as follows.
creature.py
class Creature:
def __init__(self, hp, mp, start_position, area):
self.hp = hp
self.mp = mp
self.position = start_position
self.area = area
self.oxygen = 100
def move(self, next_position):
if self.area == "land":
self.walk()
self.position = next_position
elif self.area == "water":
self.swim()
self.position = next_position
elif self.area == "sky":
self.fly()
self.position = next_position
def walk(self):
print("Teku Teku")
def swim(self):
print("Sui")
def fly(self):
print("Byun")
Since it is a group called Creature, it will be necessary to separate at least the creatures that live on the ground, the creatures that live underwater, and the creatures that live in the air. Considering that the creatures living on the ground enter the water, I feel that I have to manage the amount of oxygen. Weight management seems to be important for creatures living in the air.
Furthermore, since we are thinking about a fantasy world this time, there is a possibility that some creatures will live in the demon world contaminated with miasma, and some will live in the ground where there is no light. Along with that, it can be expected that the number of things to be implemented will increase at an accelerating rate, such as different movement methods and setting unique status.
If you think, "Aside from the rest, do you want to keep it as a villager?", I think the implementation will be as follows.
villager.py
class Villager:
def __init__(self, name, hp, start_position):
self.name = name
self.hp = hp
self.position = start_position
def move(self, next_position):
self.position = next_position
print("Teku Teku")
def speak(self, line="Hello. This is the beginning village"):
print(f"{self.name}「{line}」")
villagerA = Villager("John", 100, [0,0])
villagerA.speak()
villagerA.speak("Where did you come from?")
#Execution result
'''
John "Hello. This is the village of the beginning."
John "Where did you come from?"
'''
It's different from the previous one, and it's only for villagers, so it's easy to think about what to implement. If you treat it as an NPC, you should wander around it appropriately, and when you talk to it, speak the appropriate lines.
On the other hand, there is a desire to implement it neatly. For example, when considering creating a walled city and placing NPCs there, this Villager seems to be used with a little tinkering. The basic function of moving and talking remains the same.
Considering the expandability later, it seems that the name Villager is not the best. Try subdividing the living area, or add characteristics to each living area. It's an extension like making a child who can't attack to give variation, or a rogue who can attack on the contrary.
So what is a name with the right level of abstraction that is neither too high nor too low? It can change as much as you like depending on the specifications, but the reasonable points are as follows.
resident.py
class Resident:
def __init__(self, name, hp, start_position):
self.name = name
self.hp = hp
self.position = start_position
def move(self, next_position):
self.position = next_position
def speak(self, line="Hello"):
print(f"{self.name}「{line}」")
citizenA = Resident("John", 100, [0,0])
citizenA.speak()
villagerA = Resident("Mary", 100, [0,10])
villagerA.speak("Hello. Is this South City?")
#Execution result
'''
John "Hello"
Mary "Hello. Is this a South City?"
'''
I named it Resident because it lives somewhere. This includes villagers and citizens. It may be okay to create an aerial city citizen.
The higher the level of abstraction, the more things to implement. Taking a vehicle as an example, if you try to implement it as Transportation instead of Car, it will include airplanes and ships, and the amount of implementation will increase again.
On the other hand, lowering the level of abstraction reduces the amount of work to be implemented, but naturally narrows the range of use. Similarly, taking a vehicle as an example, implementing Bus instead of Car will narrow the scope of consideration and make implementation easier. On the other hand, considering the application to Taxi, which also carries customers, it will take another time and effort.
--If the level of abstraction is too high, there will be more things to implement. ――If the level of abstraction is too low, it will take time and effort to reuse it for others.
From the next time onward, we plan to summarize abstract base classes and inheritance and synthesis / delegation.
Recommended Posts