Toon posts:

[java] Hiëarchie superklassen - interfaces

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Beste tweakers,

Ik had al eerder een topic geopend in verband met een werk dat we moeten maken voor school, en hier heb ik nu nog een vraag over. Mijn vorige vraag ging over de klasse "Hero". Objecten van deze klasse moet je zien als Hero's uit een MMORPG (uiteraard heel vereenvoudigd). Hero's moeten nu wapens kunnen dragen en harnassen alsook rugzakken die zowel wapens als harnassen als andere rugzakken kunnen bevatten. Rugzakken, wapens en harnassen hebben een aantal dingen gemeenschappelijk waaronder een veld "ID" en een veld "Holder". De Holder kan dus zowel een rugzak zijn als een Hero.

Hero is een zeer uitgebreide klasse die we dus eerder hadden uitgewerkt.

We moeten nu dus een efficiënte hïerchie zoeken van superklassen en/of interfaces. Het is voor ons redelijk duidelijk dat er een (abstracte) superklasse moet zijn waarvan wapens, harnassen en rugzakken van overerven.
Aan de andere kant zou er ook een superklasse Holder kunnen zijn waarvan Hero's en rugzakken overerven.
Meervoudige overerving in Java is echter niet mogelijk.
We doen het nu op volgende manier:
Afbeeldingslocatie: http://i42.tinypic.com/10ekkcm.jpg
We gebruiken een interface Holder om het probleem van meervoudige overerving te vermijden. Dit is eigenlijk de enige reden waarom we een interface daarvoor gebruiken (en deze interface zal dus redelijk kaal zijn). Aangezien interfaces eigenlijk dienen om klassen te groeperen die dezelfde gedragingen hebben is het dus mss niet echt een verantwoorde keuze.
Er moet trouwens niet gelet worden op het feit dat "Weapon" en "Armor" overerven van een nogal niets zeggende klasse "Test1", dit is een tijdelijke benaming.
Verder laten we rugzak overerven van "Containable" omdat mss in de toekomst er nog handtassen oid kunnen bij komen :) .
We zouden ook Portable als een interface kunnen definïeren maar dan kunnen we geen gemeenschappelijke velden e.d. definïeren.

In grote lijnen is ons probleem dus als volgt: 3 klassen die op elkaar gelijken: wapens, harnassen, rugzakken. En 2 klassen die ook 1 functie gemeenschappelijk hebben: rugzakken en Hero's.
We zoeken dus een goed klassen diagram.

We vragen ons dus af of er Tweakers zijn die al een dergelijk probleem hebben getackled en ons hier wat tips kunnen over geven.

Onze excuses voor de lange topicstart en bedankt voor de mensen die moeite hebben gedaan om tot hier te lezen :)

Bij voorbaat dank :)

Acties:
  • 0 Henk 'm!

  • Orphix
  • Registratie: Februari 2000
  • Niet online
Kijk eens naar het Composite Pattern.

Verder is het gebruik van een interface goed. Sterker nog, interfaces zijn vaak 'netter' dan inheritance, omdat je polymorphisme wilt bereiken op basis van interface, en niet op implementatie. Bijvoorbeeld wapens en harnassen hebben eenzelfde interface (bv IInventoryItem), maar hoeven niet direct een implementatie te delen (base class), immers zijn er, in real-life althans, weinig overeenkomsten tussen een wapen en een harnas.

Acties:
  • 0 Henk 'm!

  • zwippie
  • Registratie: Mei 2003
  • Niet online

zwippie

Electrons at work

Mijn eerste impulsieve (het is al laat :)) ingave is:

Maak een duidelijk onderscheid tussen je hero en zijn benodigdheden. Je hebt je hero die je dingen wil laten doen (middels zijn uitrusting): store/retreive (backpack), wield (weapon), wear (armor). Je backpack is een Storage die zowel Items als andere Storages kan bevatten. Een Item is een abstracte klasse (of interface?) met eigenschappen als size. Een concrete Item instantie zoals bv een bepaald type weapon heeft dan als base class Item en als interface Wearable.

Door interfaces voor armours en weapons te gebruiken kun je meerdere 'rollen' aan een item geven. Je dwingt bv af dat een weapon een getDamage(opponent) methode heeft om te bepalen hoeveel schade er wordt aangericht.

Nomgaals, het is al laat, maar misschien kan dit je weer aan het denken zetten.

edit: Wat Orphix zegt idd: met interfaces kun je ook een soort 'polymorphisme' bereiken.

[ Voor 5% gewijzigd door zwippie op 27-03-2010 02:01 ]

How much can you compute with the "ultimate laptop" with 1 kg of mass and 1 liter of volume? Answer: not more than 10^51 operations per second on not more than 10^32 bits.


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Dit heeft niet zozeer met Java te maken en des te meer met algemeen software-ontwerp. Waar hoort mijn topic?

PRG>>SEA

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt voor de replies

@Orphix: die link lijkt me wel handig, zal er in combo met google verder naar kijken.

@Zwippie: ook thnx

Jullie raden me wel aan om vooral met Interaces te werken, maar als ik me niet vergis kunnen interfaces geen velden hebben (behalve dan constanten die static final zijn). En aangezien zowel wapens, harnassen en rugzakken een veld "Holder" en een veld "Identification" (en wss ook nog het gewicht) hebben lijkt me dat toch een reden om de superklasse portable te behouden.

Acties:
  • 0 Henk 'm!

  • Orphix
  • Registratie: Februari 2000
  • Niet online
Verwijderd schreef op zaterdag 27 maart 2010 @ 11:25:
Bedankt voor de replies

@Orphix: die link lijkt me wel handig, zal er in combo met google verder naar kijken.

@Zwippie: ook thnx

Jullie raden me wel aan om vooral met Interaces te werken, maar als ik me niet vergis kunnen interfaces geen velden hebben (behalve dan constanten die static final zijn). En aangezien zowel wapens, harnassen en rugzakken een veld "Holder" en een veld "Identification" (en wss ook nog het gewicht) hebben lijkt me dat toch een reden om de superklasse portable te behouden.
Als je erover nadenkt is een classe een implementatie én een interface. Als er geen interface zou zijn, zou je ook niet kunnen werken met instanties van die classe (bv als alles private zou zijn). Alle code die in je programmatuur gebruikt maakt van die objecten communiceren niet met de implementatie, maar met de (impliciete) interface. In je design ga je bepalen hoe informatie gerepresenteerd en gestructureerd gaat worden en hoe operaties kunnen worden uitgevoerd door communicatie tussen deze structuren. Dat is je design, en dat is het niveau waarop je nu moet analyseren. Heb je eenmaal een design dan ga je dit vertalen naar een implementatie, en pas _dan_ga je bedenken dat deze data elementen inderdaad vaker voorkomen en dat het wellicht handig is om hiervan een base classe te maken om deze implementatie te delen. (en dus niet automatisch de interface!)

Maar software design is een kwestie van heuristieken; er zijn geen harde regels en het is niet altijd even duidelijk ;) Succes ermee!

Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Verwijderd schreef op zaterdag 27 maart 2010 @ 11:25:

Jullie raden me wel aan om vooral met Interaces te werken, maar als ik me niet vergis kunnen interfaces geen velden hebben (behalve dan constanten die static final zijn).
Ik weet niet hoe Java dat precies doet, maar in C# kun je gewoon properties definieren in je interfaces:

C#:
1
2
3
4
5
public interface Tral
{

  String Test { get; set; }
}

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 02-10 16:55
Grijze Vos schreef op maandag 12 april 2010 @ 17:33:
[...]

Ik weet niet hoe Java dat precies doet, maar in C# kun je gewoon properties definieren in je interfaces:

C#:
1
2
3
4
5
public interface Tral
{

  String Test { get; set; }
}
dat kan in Java dus niet (aangezien je een interface niet kan instantieren en zo nog een reeks dingen), maar je kunt wel de setter en getter (indien van toepassing) definiëren. De implementatie kan dan zelf kiezen hoe deze gegevens dan opgeslagen worden. addItem(Item item) zou het Item gewoon in een Map kunnen opslaan, of hij kan het gelijk doorgeven aan een database die het opslaat - om maar een voorbeeld te noemen.

Maar ik denk dat die syntax in C# aangeeft dat er een functie getTest en setTest voor een String type gedefinieerd moeten zijn, ipv daadwerkelijk die gegevens op te slaan (als ware het een property).

@TS, lijkt me dat een interface Holder of Container (of ItemContainer, als je specifieker wilt zijn) wel zal werken. Je Hero implements Container, je ConcreteContainer implements Container (waar ConcreteContainer dan bijvoorbeeld een property naam heeft zoals Backpack of Handtas), etc.

Je Hero implementeert natuurlijk ook een aantal andere interfaces, natuurlijk, het is niet alleen een container.

Acties:
  • 0 Henk 'm!

Verwijderd

Gebruik de concepten waarvoor ze bedoeld zijn. Als je een concept gaat "misbruiken" om iets voor elkaar te krijgen is dat vaak een teken dat je ruwe design niet klopt. Interfaces gebruiken om "meervoudige overerving" mogelijk te maken is daar een goed voorbeeld van.

Meervoudige overerving is m.i. een fout concept, het is niet voor niets dat dit in Java en C# niet mag.

gebruik overerving waar het voor bedoeld is, zoals bv:
SpelObject -> Equipment -> Sword -> Fire Sword
SpelObject -> Equipment -> Sword -> Ice Sword
SpelObject -> Equipment -> Armour -> Light Armour
SpelObject -> Equipment -> Armour -> Heavy Armour
SpelObject -> Item -> UsableItem
SpelObject -> Item -> Key Item
de "SpelObject" base class hier bevat de meest rudimentaire properties die alle objecten in het spel hebben, zoals bv Weight.
Polymorphise bereik je door overriden van methodes en properties. Bv. de methode CalculateDamage in de Sword klasse wordt overridden
in FireSword en IceSword om de damage van die zwaarden te berekenen.

En gebruik interfaces waar die voor bedoeld zijn.
Ipv een interface "holder" zou ik eerder denken aan een iContainer of een iStorage interface ofzo om aan te geven dat iets een container is/kan zijn.
Een iContainer kan dan overeenkomen dat een collectie van items als property moet worden geimplementeerd (iets van List<SpelObject> Content in C#) die de content van die container voorstelt, alsook een Store en Retrieve methode.
Zowel Hero als Backpack moeten dan iContainer implementeren. Een Backpack kun je dan zelf weer laten ervan de de Item base class zodat een Backpack zelf ook in een Backpack kan zitten. Je kunt dan overal een iContainer van maken ongeacht wat. Bv vijanden kunnen ook iContainers zijn zodat je ze kunt looten etc., maar die erven niet van "SpelObject"
Een Containable base class is dan ook niet meer nodig.

Is het overigens zinvol dat een object (Item) weet waar het in zit? (dus dat het een "Holder" heeft)? Dit lijkt mij nl. op het eerste gezicht overbodig en onnodig complex. Waarom boeit dat?

Tot slot, interfaces bevatten nooit implementatie, dus ook geen fields. YopY heeft gelijk met die C# syntax, dat geeft alleen maar aan dat er een property moet zijn met die naam en een GET en SET methode. Hoe die property de waarde opslaat en ophaalt boeit niet.
Pagina: 1