En ole ihan varma tästä, mutta muistelen että Oliosuuntautuneen Ohjelmistokehityksen kurssilla mainittiin että olio voi saada ominaisuudet useasta luokasta. En ymmärtänyt sitä silloin enkä ole varma ymmärränkö vieläkään. Esitämpä ensin ongelmani.
TKE:ssä on monenlaisia ammuksia (Ammuksilla tarkoitan niitä instansseja jotka lentävät kentällä, en niitä jotka pelaajalla on taskussa). Osa ammuksista on fyysisiä entiteettejä (niillä on hitbox sekä normaalit fysiikkalaskut pätevät niihin) ja osa on vain yksinkertaisia matemaattisia malleja (kuten vanhan tk:n ammukset jotka joko osuvat viholliseen tai välähtävät vain maassa ja seinillä). Ongelma on se että kaikilla ammuksilla on ammusten ominaisuuksia (kuten vaurio ja tuhoutuminen osuessa), mutta panoksilla on myös ominaisuuksia jotka liittyvät niiden lentoratoihin (kuten äsken mainitsin fysiikka-ammuksista ja matematiikka-ammuksista). Tässä nykyinen entiteettihierarkia panosten osalta, sisennykset ilmaisevat periytymisen:
TMapEntity TVisualMapEntity TProjInstaGib TPhysEntity TCreature TBasicPlayer TProjPhys
TProjInstaGib on matemaattinen ammus ja TProjPhys on fyysinen. Periaatteessahan tässä ei ole ongelmaa kun tekee vain tuplana sen kuvitellun yleisen ammusluokan ominaisuudet kumpaankin luokkaan, mutta en haluaisi tehdä spagettikoodia. Ongelmia tulee lisäksi siinä kun TCreature ja TPhysEntity ottavat vastaan osuman ammuksesta. Näille luokille on ihan sama onko ammus InstaGib vai Phys, mutta koska yleistä ammusluokkaa ei ole, on hieman hankala lähettää ammuksen tietoja näiden luokkien käsiteltäviksi.
Eli kysymyksiin: Voiko olioon kapseloida toiminnallisuutta kahdesta eri luokasta? Onko ongelmaan joku muu järkevämpi ratkaisu?
Tuleeko ongelmia lisää jos yleisen ammus-luokan tekisi?
Delphissä voi käyttää abstrakteja aliohjelmia tai sitten hieman epävirallisempana keinona viitettä aliohjelmaan. Tuon aliohjelman voi määritellä kussakin luokassa ammuksen tyypin mukaan.
1 esimerkki viitteestä Delphin omissa kirjastoissa vaikka TButton.onClick event jolle design tila antaa arvon pääohjelman koodista.
User137 kirjoitti:
Tuleeko ongelmia lisää jos yleisen ammus-luokan tekisi?
Delphissä voi käyttää abstrakteja aliohjelmia tai sitten hieman epävirallisempana keinona viitettä aliohjelmaan. Tuon aliohjelman voi määritellä kussakin luokassa ammuksen tyypin mukaan.
1 esimerkki viitteestä Delphin omissa kirjastoissa vaikka TButton.onClick event jolle design tila antaa arvon pääohjelman koodista.
Jos tekee erillisen ammusluokan niin silloin TProjPhysille pitäisi kopioida fyysisen objektin ominaisuudet, ja sitä koodia riittääkin enemmän kuin tarpeeksi. En edes näkisi sitä mielelläni vaihtoehtona.
Mietin myös sellaista vaihtoehtoa että TProjPhysin voisi korvata vain normaalilla entiteetillä joka törmätessään viholliseen vapauttaa itsensä ja luo uuden TInstaGib-ammuksen, joka hoitaa sitten itse vauriontekemisen. Menee tosin aika järjettömän kuulloiseksi.
Tarkoititko siis että tehdään itsenäiset proceduurit panosten toiminnallisuuden käsittelyyn ja sitten panosluokista vain kutsutaan niitä?
Delphissä ei ole moniperintää. Helpoiten pääset vastaavaan efektiin luultavasti juuri noilla ulkoisilla funktioilla. Yksi mahdollisuus on laittaa nämä yleiset ominaisuudet kuitenkin omaan luokkaansa ja käyttää tätä luokkaa sitten kummastakin ammustyypistä:
TProjGeneral = class function ...; end; TProjInstaGib = class of TMapEntity General: TProjGeneral; end; TProjPhys = class of TPhysEntity General: TProjGeneral; end;
Metabolix kirjoitti:
Yksi mahdollisuus on laittaa nämä yleiset ominaisuudet kuitenkin omaan luokkaansa ja käyttää tätä luokkaa sitten kummastakin ammustyypistä:
TProjGeneral = class function ...; end; TProjInstaGib = class of TMapEntity General: TProjGeneral; end; TProjPhys = class of TPhysEntity General: TProjGeneral; end;
No tuo alkaa näyttämään jo säädylliseltä ratkaisulta. Kiitti Metabolix, oot pro.
Aihe on jo aika vanha, joten et voi enää vastata siihen.