Egy játékban szeretném, ha az ellenségek osztálya nyilvántartaná a létező ellenségeket, és szeretném, hogy ha a példányok meghalnak, akkor törölnék magukat. Szerintetek jól végzi-e el ezt a feladatot az alábbi program?
Ha nem, mi vele a baj? Azért vagyok bizonytalan mert jó sok cikk szerint erre weak refernces való (pl: https://stackoverflow.com/questions/37232884/in-python-how-to-remove-an…).
- 1824 megtekintés
Hozzászólások
Nem néztem meg a programodat, de miért kellene egy osztálynak ismernie a létező példányait?
És mit értesz pontosan az alatt, hogy az osztály? Az összes példány osztozni fog egy közös listán?
Persze lehet, hogy nem értem az alap problémát. Esetleg leírnád, hogy mit is szeretnél megoldani?
- A hozzászóláshoz be kell jelentkezni
"És mit értesz pontosan az alatt, hogy az osztály? Az összes példány osztozni fog egy közös listán?"
"Esetleg leírnád, hogy mit is szeretnél megoldani?"
Egy játékban szeretném, ha az ellenségek osztálya nyilvántartaná a létező ellenségeket, és szeretném, hogy ha a példányok meghalnak, akkor törölnék magukat.
- A hozzászóláshoz be kell jelentkezni
Na jó, ha nem akarsz válaszolni, akkor hagyjuk!
- A hozzászóláshoz be kell jelentkezni
Ez valami vicc?
- A hozzászóláshoz be kell jelentkezni
Nézd. Kérdeztem valamit.
Válasz helyett idéztél valamit, amit már láttam, meg adtál egy programrészletet, amivel nem tudok mit kezdeni.
2 kérdés, 0 válasz.
Teljesen mindegy, hogy nem tudsz vagy nem akarsz válaszolni, a végeredmény ugyanaz.
- A hozzászóláshoz be kell jelentkezni
Klasszik OOP szerint:
- csinálnék egy listát amiben ellenség típusú objektumok lehetnek
- ez a lista legyen egy singleton
--
Gábriel Ákos
- A hozzászóláshoz be kell jelentkezni
És akkor az ellenség példánynak az a dolga, hogy amikor érzi, hogy meghal, akkor szól a singletonnak, hogy törölje őt a listából? Ebben a feladatban nem létrehozott példányok nyilvántartása az új, hanem az, hogy az elpusztulók törlődjenek.
- A hozzászóláshoz be kell jelentkezni
Hozz létre egy __del__(self) metódust, ami kitörli a nyilvántartásból az objektumát, mielőtt a szemétgyűjtő törölné magát az objektumot.
Szerk.: Ez mégsem oldja meg automatikusan a problémát, mert a __del__() meghívásának időpontja nem látható előre.
--
eutlantis
- A hozzászóláshoz be kell jelentkezni
Így van, sajna:(
- A hozzászóláshoz be kell jelentkezni
Valami ilyesmit tennék:
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
class Soldier():
instances = {} # name:self
def __init__(self, name):
self.name= name
if name in self.instances:
raise NameError("Duplikált név: '"+name+"'")
else:
self.instances[name]=self
@classmethod
def isalive(cls,name):
return name in cls.instances
def fight(self):
if not self.isalive(self.name):
return None
else:
# ....
return True
def shoot(self):
if not self.isalive(self.name):
return None
else:
# ....
return True
@classmethod
def trupp(cls):
return list(cls.instances.keys())
@classmethod
def kill(cls,name):
ident= cls.instances.pop(name,None)
if __name__ == "__main__":
enemy=[ Soldier(name) for name in ['Alpha', 'Beta', 'Gamma'] ]
print( Soldier.trupp())
try:
alpha2=Soldier('Alpha')
except NameError as event:
print(event)
Soldier.kill('Gamma')
print( Soldier.trupp())
jedi=Soldier("Jedi")
print( Soldier.trupp())
print( jedi.fight() )
jedi.kill("Jedi") # öngyilkosság?
print( jedi.fight() )
És egy katona bármit is tenne (fight,shoot), előtte megnézné, hogy egyáltalán még életben van-e. Még meghalni is csak akkor szabad, ha még él:-)
--
eutlantis
- A hozzászóláshoz be kell jelentkezni
"előtte megnézné, hogy egyáltalán még életben van-e"
Amit nyilván egy díszítővel oldana meg az ember.
Átfutottam, de elsőre nem látom a lényegi különbséget az enyémhez képest. Segíts!
- A hozzászóláshoz be kell jelentkezni
Eventek kellenek neked szerintem.
https://stackoverflow.com/questions/1092531/event-system-in-python/
- A hozzászóláshoz be kell jelentkezni
Nem feltétlen akarom bonyolítani a kódot, ha nem kell mindenképp. Az a kérdés inkább, hogy miért mozdul el a nép attól az egyszerű módszertől, ami az én kódomban van. Miért nem elegendő annyi?
- A hozzászóláshoz be kell jelentkezni
Mert rugalmatlan, tightly-coupled.
Mi van akkor, ha több alrendszernek is kezelnie kell azt a dolgot, hogy "meghalt egy ellenség"?
Leírod a "halálkezelő" kódba, hogy történjen X meg Y , meg Z? Nem kiterjeszthető a kódod, valamint az Ellenség osztály tud arról, hogy a rendszer rajta kívül milyen komponensekből áll.
Míg ha eseménykezelés van:
1. Meghal egy ellenség, emittál egy "MEGHALT_EGY_ELLENSÉG" eseményt.
2. Akit érdekel a "MEGHALT_EGY_ELLENSÉG" esemény (pl. UI, ellenségek listája, bárki más), elkapja ezt az eseményt, és cisnál vele, amit akar.
A jövőben, ha új viselkedést akarsz hozzátenni a rendszerhez, ami a "MEGHALTAM" eseményre csinál valamit, NEM kell belenyúlnod az Ellenség osztály kódjába.
- A hozzászóláshoz be kell jelentkezni
a linkelt SO kérdésben olyat csinálnak, hogymikor a GC szabadítaná fel az objektumot, akkor kerüljön ki a listából.
Ha jól értem, neked jól megfogható halál eseményed van, amikor ki tudod szedni kézzel a listából - és minden referenciát megszüntetsz rá, a GC meg majd összekaparja valamikor. Ehhez nem kell weakreference, mehet az az út, amit elkezdtél.
- A hozzászóláshoz be kell jelentkezni
Jól érted, és köszönöm!
- A hozzászóláshoz be kell jelentkezni
Lehet, hogy öreg vagyok már, de nem statikus metódust nem egy példányon keresztül hívni elég betegnek tűnik. @classmethod helyett miért nem @staticmethod van? A this(itt cls) paraméter meg nem kell, hisz ezek nem egy példányhoz kötött metódusok.
Én így csinálnám:
- A hozzászóláshoz be kell jelentkezni
Azért nem Test.függvénynév néven hívom, mert akkor baj van, ha esetleg alosztályba kerülnek ezek.
Amikor classmethod-ot hívok self-fel, azt csak úgy tudom, lévén a függvény belsejében nincs cls-em, a self-nek persze szintén nincs meg az a metódusa, de majd meghívódik az osztályé. Engem is zavar, épp ezért filózok el a self.__class__.függvény híváson.
És hogy miért nem staticmethod? Akár jó is lehet. Ugye úgy tudom, hogy akkor használ az ember staticot és nem class-t, ha van ugyan köze a függvénynek az osztályhoz, de nem használja a benne lévő cuccokat, csak logikailag jó, ha ott a függvény és nem máshol. Itt meg ugye használjuk az osztályváltozót (a listát), hát ezért. De ez csak válasz a kérdésedre, nem a tuti igazság...
- A hozzászóláshoz be kell jelentkezni
"Normális" programnyelvekben (C++ pl.) meg sem hívhatsz az osztály nevével nem statikus metódust (hisz nem lesz this (self, cls)). Az a lista az oszályhoz tartozik, nem minden egyes példányhoz, így az azt kezelő metódusok is statikusak, főleg, hogy Test:xxxx-ként hívod őket, nem pedig a=Test(), a.xxx. Igaz, pythonban itt lehet gányolni, csak minek, főleg, hogy a self tök felesleges ezekhez a metódusokhoz.
- A hozzászóláshoz be kell jelentkezni
Hát én már nagyon rég átnyergeltem Go-ra, úgyhogy előre is bocsi.
De anno se szerettem ezeket a típusokat, osztályokat, öröklődést - sokszor megégettem magam...
Ha jól látom, itt egy darab listába (dict, ha gyorsabbat akarsz) kell karbantartani az élő példányokat.
Tehát kell egy globális vagy csilivili osztály PÉLDÁNY aminek a pop/push metódusát meg kell hívni __init__ és kill esetén.
Én ezt nem keverném bele az osztályba, simán kapja meg az __init__-ben hogy melyik dict-ben kell ezt nyilvántartani, és kész.
- A hozzászóláshoz be kell jelentkezni
Miért nem kevernéd bele?
- A hozzászóláshoz be kell jelentkezni
Mert a single responsibility jó dolog:
https://en.wikipedia.org/wiki/Single_responsibility_principle
Amúgy meg kérdés, hogy mi a célod az alkalmazással, ha nem érdekel a kódminőség, akkor mindegy, nem kell ilyen kérdésekkel foglalkoznod, de akkor meg ugye miért tetted volna fel a kérdést egyáltalán...
- A hozzászóláshoz be kell jelentkezni
Azt nem értem a wikipédia-cikk pédája alapján, hogy meddig atomizáljuk a felelősségeket: aszondja, hogy a jelentést az egyik osztály compile-ja. Na de ez is szétszedhető még: az egyik osztály kinyeri a szükséges adatokat, a másik kiszámolja, amit kell.
Valamilyen értelemben nálam is s.r. van: egy osztály dolga minden, ami azzal az osztállyal kapcsolatos: megy, lő, ütközik, meghal és törlődik.
Vagy valamit nem értek?
- A hozzászóláshoz be kell jelentkezni
Halihó!
Megy, lő, ütközik, igen, ezek megfelelnek az SR-nek. A “meghal”, talán belefér, de ez már neccesebb, attól függ milyen mellékhatásai vannak a "halálnak". A törlődik, viszont semmiképp. Ha a törlést is az osztályra bízod, akkor gyakorlatilag felruházod a “kezeld az erőforrásokat” responsibilityval.
Én csinálnék pl. egy “EnemyManager” osztályt, ahol tárolnám a pédányokat. Ez az osztály végezné az ellenségek spawnolását, nyilvántartását és törlését is.
A törlés ugyanazért nem illik ide, amiért a spawn sem (ami helyesen az osztályon kívül, a 28. sorban van a kódodban).
- A hozzászóláshoz be kell jelentkezni
Alapvetően "jóvanazúgy," ha az neked megfelel, csak majd visszaüthet ha megnő. De akkor úgyis igazodsz.
A static metódusokat szokták kerülni, ha lehetséges, mivel az öröklődéssel nem működik szépen együtt.
Itt ez megoldható lenne egy külső osztállyal, akinek pont a lista nyilvántartása lenne a feladata és lenne két nagyon egyszerű osztály. Az egyszerűség jó.
Ami nekem személy szerint sokkal jobban szúrja a szememet, az a printelős tesztelés. Nem számottevően nehezebb unittest-esen megfogalmazni, viszont sokkal hasznosabb.
_______Peter
I am a stone. I do not move.
- A hozzászóláshoz be kell jelentkezni