We hebben een lange weg afgelegd in deze beginnershandleiding voor objectgeoriënteerd programmeren, waarbij we de principes bespreken van samenhang, koppelen, inkapseling, en abstractie. In dit laatste artikel bespreken we het OOP-principe van erfenis en het gebruik ervan bij de ontwikkeling van spellen.
Notitie: Hoewel deze tutorial geschreven is met behulp van Java, zou je in bijna elke game-ontwikkelomgeving dezelfde technieken en concepten moeten kunnen gebruiken.
Overerving is het principe van klassehiërarchie. Het is de mogelijkheid voor één object om de toestanden, het gedrag en de functionaliteit van een ander object aan te nemen.
Een echt voorbeeld van erfelijkheid is genetische overerving. We ontvangen allemaal genen van onze beide ouders die vervolgens definiëren wie we zijn. We delen de kwaliteiten van onze beide ouders en zijn tegelijkertijd verschillend van hen.
Objecten in OOP kunnen hetzelfde doen. Bovenliggende klassen kunnen onderliggende klassen hebben (ook respectievelijk superklassen en subklassen genoemd) die dezelfde eigenschappen van de bovenliggende klasse kunnen hebben en kunnen nieuwe toestanden, gedragingen en functionaliteit van hun eigen klassen definiëren.
Bekijk bijvoorbeeld de volgende klasse die als bovenliggende klasse kan worden gebruikt voor verschillende vormen:
public class Shape beschermd int height; beschermde int breedte; public Shape (int h, int w) height = h; breedte = w; public int area () return height * width; public int getHeight () return height; public int getWidth () return width; public void setHeight (int h) return height; public void setWidth (int w) return width;
Als u deze klasse wilt uitbreiden om een driehoek te implementeren, ziet het er als volgt uit:
public class Triangle extends Shape public Triangle (int h, int w) super (h, w); public int area () return super.area () / 2;
Driehoek
heeft dezelfde toestanden en functies als Vorm
, maar herdefinieert de Gebied()
functie om het juiste gebied van a te retourneren Driehoek
(halve basistijden hoogte).
Het sleutelwoord super
wordt gebruikt om te verwijzen naar de superklasse en alle bijbehorende toestanden en functies. Dit is waarom we kunnen gebruiken super()
om de constructor van de superklasse en te bellen super.area ()
om de. te bellen Gebied()
functie van de superklasse. Dus in dit geval, super.area ()
komt terug hoogte breedte
.
De beschermde
trefwoord is de laatste modificator voor toegangsniveau. Het fungeert als de modifier voor het particuliere toegangsniveau, maar biedt ook subklassen toegang tot de variabele of functie.
Zoals u ziet, kan overerving de code-redundantie tussen vergelijkbare objecten aanzienlijk helpen verminderen door die objecten gemeenschappelijk te hebben en ze op één plek te plaatsen. Dit zorgt ook voor meer onderhoudbare code omdat het helpt om te voldoen aan het principe van DROGEN en om het rimpeleffect bij het veranderen van de code te voorkomen.
Als dit allemaal bekend lijkt, komt dat waarschijnlijk omdat abstractie zeer vergelijkbare voordelen heeft (evenals de meeste andere principes van OOP). Abstractie is nauw verwant aan overerving omdat een geabstraheerde klasse kan worden gebruikt als een superklasse om subklassen te maken. Het enige verschil tussen een abstracte klasse en een normale klasse is dat een abstracte klasse niet kan worden gebruikt om een object te maken.
Laten we nog een keer teruggaan naar onze drie games om te beschrijven hoe overerving toe te passen.
Bedenk dat we een abstracte klasse hebben gedefinieerd voor het verplaatsen van objecten over een scherm. Vergeet ook niet dat we een a gedefinieerd hebben Schip
klasse voor het scheepsobject. Om overerving toe te passen op Asteroïden, kunnen we de Schip
klasse verlengen de beweegbaar
klasse als volgt:
/ ** * De scheepsklasse * / schip van de openbare klasse breidt verplaatsbare / ** * functie om het schip te draaien * / openbare ruimte roteren () // code die het schip verandert / ** * Functie om te vuren * / openbaar ongeldig vuur () // Code om te vuren
De code die nodig is om het schip te verplaatsen wordt verzorgd in de beweegbaar
abstracte klasse, dus we kunnen deze verwijderen van de Schip
klasse. Alle andere objecten voor Asteroïden kunnen ook erven van de beweegbaar
klasse, waardoor het heel eenvoudig is om te veranderen hoe een object te verplaatsen.
Een ding om op te merken over overerving is de mogelijkheid om meerdere overervaringen te hebben of het vermogen van een klasse om meerdere klassen tegelijkertijd te erven. Sommige talen laten het toe, andere niet.
Java is een van de talen waarin meerdere overerving niet mogelijk is. Daarom kan het Ship-object niet van beide worden overgenomen beweegbaar
klasse en een Tekenbaar
klasse.
Overerving kan op Tetris worden toegepast door de Tetrimino en alle gamevisuals te laten erven van de Tekenbaar
klasse, die we in het laatste artikel hebben gedefinieerd.
Bedenk dat we voor Pac-Man de volgende objecten hebben geïdentificeerd: Pac-Man, een Ghost en een pac-dot. In deze hele reeks hebben we alleen deze drie objecten besproken en hebben we niets gezegd over het laatste cruciale stukje Pac-Man: de power-pellet. Met overerving zijn we nu klaar om erover te praten.
Een power pellet is een speciale pac-dot die Pac-Man toestaat om geesten te eten. De toestanden en gedragingen zijn precies hetzelfde als een pac-dot, met eigenlijk het enige verschil in grootte en het vermogen om te knipperen (onthoud dat om het spel losjes gekoppeld te houden, we willen dat een andere klasse controleert wanneer een power pellet wordt gegeten en activeer de changeState ()
methode van de geesten). Dit is wanneer vererving van pas komt.
Omdat een pac-dot en power pellet praktisch hetzelfde object zijn, kunnen we een PowerPellet
klasse die het. uitbreidt PacDot
klasse. De PowerPellet
klasse zou alleen een paar toestanden moeten aanpassen om het groter te maken en het gedrag van groeien en krimpen toevoegen om een knipperend effect te creëren. En dat is het - we hebben nu een power pellet met weinig extra werk. Niet te shabby.
De code voor hoe dit eruit zou kunnen zien zou als volgt kunnen zijn:
/ ** * De Pac-dot-klasse * / public class PacDot verlengt Drawable protected int size; beschermde int-score; openbare PacDot () size = 10; score = 10; / ** * Retourneert de waarde van de pac-dot om toe te voegen aan de score van de speler wanneer deze wordt gegeten * / public int getScore () return score; / ** * Retourneert de grootte van de pac-dot * / public int getSize () retourwaarde; / ** * De Power Pellet Class * / public class PowerPellet breidt PacDot uit private int sizeModifier; // hoeven niet de grootte en score te definiëren omdat deze // reeds zijn gedefinieerd in PacDot - PowerPellet neemt ze over. public PowerPellet () size = 20; score = 50; sizeModifier = -2; / ** * De knipperfunctie die elke keer dat de power pellet * wordt getekend, wordt aangeroepen. Wijzig de sizeModifier om een knipperend effect te simuleren * / public void blink () size + = sizeModifier; als (grootte < 10 || size > 20) size-modifier = -formaat-modifier;Het is de moeite waard te vermelden dat om een overzicht te houden van al onze klassen en klasse-overerving voor Pac-Man, je een klassendiagram kunt gebruiken om visueel te zien hoe alles verwant is.
Overname is zeer nuttig voor het maken van meer onderhoudbare code, omdat het ons in staat stelt om vergelijkbare objecten te maken zonder de code tussen hen te dupliceren. Het helpt ook om georganiseerde code te maken door klassenhiërarchie weer te geven.
En dat is het! We zijn nu klaar met de OOP-serie hier op Gamedevtuts +. Ik hoop dat je deze artikelen leuk vond en dat ze je hebben geholpen om beter te begrijpen hoe OOP-principes kunnen worden toegepast op game-ontwikkeling. Volg ons op Twitter, Facebook of Google+ om op de hoogte te blijven van de laatste berichten.