• Post Reply Bookmark Topic Watch Topic
  • New Topic

How to handle an inheritance issue  RSS feed

 
Alfie Noakes
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have never really used inheritance with Java before, and not really much at all, so I'm not familiar with how best to achieve what I want. This seems like it would be a pretty basic question for someone with knowledge on the issue, hence why I posted in Beginning Java.

Every type of controllable object in my game is a type of Entity, and so extends Entity. This is broken down into Ship(s) and Structure(s). But I have different types of structures as well. The problem is that I use an ArrayList<Structure> to store all of a team's structures, but I need to be able to loop through that, and still be able to reference the subclasses of those structures.

For example, I have a JumpGate, which extends Structure. I need to be able to reference a particular JumpGate - as a JumpGate - and not as a Structure. However, the way that I cycle through all of the different types of structures is with an ArrayList<Structure>. I could get around this by having an ArrayList<JumpGate>, however, I would then need a seperate ArrayList for every type of Structure, which would get messy.

Sorry if that is confusing, if you need further clarification on my issue, don't hesitate to ask.

Thanks for any help.
 
Maneesh Godbole
Bartender
Posts: 11445
18
Android Eclipse IDE Google Web Toolkit Java Mac Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Check out the instanceof operator
e.g. JumpGate instanceof Structure would evaluate it to true. This way you can have a collection of Structure and identify which subclass it is.
Of course when you need to invoke a method which is part of JumpGate (and not Structure) you will need to explicitly typecast it to JumpGate
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alfie Noakes wrote:Every type of controllable object in my game is a type of Entity, and so extends Entity.

Well, that might be your first problem (but also, maybe not ).

There are two ways to declare a type: as a class, or an interface; and in many ways the latter is more flexible than the first. First off, Java only allows single inheritance, so if you want to introduce specializations, hierarchies can become quite large and brittle. On the other hand a class can implement as many interfaces as you want.

For example, I have a JumpGate, which extends Structure. I need to be able to reference a particular JumpGate - as a JumpGate - and not as a Structure.

I guess the question then is: Why? I can certainly understand the need to create a JumpGate, but the mere fact that you've "typed" it as a Structure suggests that most of the time you simply want to deal with it as a structure. Polymorphism (overriding) should allow you to run whatever methods you need to, and have a JumpGate do what a JumpGate does and and a Wall (or some other class that extends or implements Structure) do what it does.

I think maybe you need to think about how a JumpGate behaves as a Structure, rather than adding a lot of unique methods to it; otherwise you're going to have a lot of "dispatch" code, viz:which is precisely what polymorphism is meant to avoid.

Not sure if it answers your question, but hope it helps.

Winston
 
Jayesh A Lalwani
Rancher
Posts: 2762
32
Eclipse IDE Spring Tomcat Server
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Complete agreement with Winston here. ALthough, you could do what you want to do with instanceof, it's not a good idea to pepper your code with instanceof. For one, it makes it harded for you to extend your code. If you had to add a new kind of Structure, you'll have to find ll the places you are doing instanceof.

The way I like to do this is: classes describe things, interfaces describe behaviors. So, you have a jump gate, and you implemented a class called JumpGate that represents the jump gate. That's good. Now, you need to think about what can your Jump Gate do? How will other entities interact with the jump gate. Well, they could enter the jump gate right? Being able to enter is a behavior that the jump gate supports. So, define an interface called Enterable and have the JumpGate implement it. Now, if you need to implement a door, you can model it as a Door class, and have Door implement Enterable. Now. anything that can enter a Jump Gate can enter a Door too. Hold on, you can knock on a door.. but you can;t knock on a Jump Gate. So, define a Knockable interface, and have Door implement it. This allows you to define a class called TreeTrunk that implements Knockable but doesn't implement Enterable. Anything that can knock on a door can knock on the tree trunk because they will just be coded to the Knockable interface

Start thinking of modeling behaviors as interfaces. You might need a base class at all
 
Alfie Noakes
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I looked up interfaces and have read a little bit about them. I had only ever used implements Runnable before, for a thread. I think they might be useful, but I would need to learn how to best implement (pun intended) them in this circumstance.

The reason why I have everything as an Entity is because Ships can target both other Ships and Structures. It prevents the need for targetIsShip or targetIsStructure variables. I might get rid of the extending of Entity, it might be easier without it. But that wouldn;t solve my problem with the JumpGate.

So I have an ArrayList<Structure> which contains all of the structures of a particular team. This makes it nice and easy to find the nearest structure to a particular point, for instance the mouse. So if I click a mouse button, then I can easily loop through all of the structures on team 1, and find which is the closest. This is what I need.
But I also then need to be able to reference the Structure as its subclass instance from then on.

For example, if I clicked near a JumpGate (jumpGate1), it would loop through all of the Structures and find that jumpGate1 was the closest. But that is a structure, not a JumpGate. So I can't treat it as a JumpGate...

I can understand how I could have the JumpGate behaviours as an interface, but I can't understand how this would get around my issue.

After reading that Polymorphism link (which was very helpful, thanks), I think I have an idea on how to get around the issue. Could I create the JumpGates like this?:

So I would be creating a JumpGate that could be referenced as a Structure, but it would contain the overriden methods specific to a JumpGate's functionality. These overriden methods could be in the form of an interface?
If so, then would I need to implement the JumpGate's behaviour interfaces in the Structure classm but leave the methods empty, and then fill them out in the JumpGate class?

I know that if class B is a subclass of class A, and class A implements Interface1, does class B automatically implement that, or do I have to write "implements Interface1" in class B as well?
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alfie Noakes wrote:For example, if I clicked near a JumpGate (jumpGate1), it would loop through all of the Structures and find that jumpGate1 was the closest. But that is a structure, not a JumpGate. So I can't treat it as a JumpGate...

I can understand how I could have the JumpGate behaviours as an interface, but I can't understand how this would get around my issue.

Actually, it's far more likely that JumpGate would implement a Structure interface. However, how you proceed from there depends very much on what needs to happen in your game.

So: you click near a JumpGate. Now what happens? More importantly, what would happen differently if you clicked near a Ship, or a Wall, or a Building (I'm just picking examples, I have no idea which classes of yours are actually Structures).

It's this that you have to work out because, ideally, what you would like to do is call the same method on any one of them, and simply have them behave differently.

So I would be creating a JumpGate that could be referenced as a Structure, but it would contain the overriden methods specific to a JumpGate's functionality. These overriden methods could be in the form of an interface?
If so, then would I need to implement the JumpGate's behaviour interfaces in the Structure class, but leave the methods empty, and then fill them out in the JumpGate class?

Absolutely right. And you would have to do the same thing for ALL classes that are Structures.

I know that if class B is a subclass of class A, and class A implements Interface1, does class B automatically implement that, or do I have to write "implements Interface1" in class B as well?

No. It's implicit.

I have to say, you've chosen quite a task for your first foray into inheritance; I hope it's not too ambitious. That said, if you can get it to work, I suspect you'll learn a LOT.

You might want to have a look at the WhatNotHow (←click→) and StopCoding pages, because I suspect you have a fair bit of planning ahead of you before you get too deep into coding.

HIH

Winston
 
Alfie Noakes
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're very correct about wanting to jump straight into coding. I had a read of both the links, and I have actually gotten into the habit of writing stuff down that I'm getting stuck on, working through it on paper first. It seems quite helpful.

I have thought about how I would like it to work, but I don't believe I have a sufficient understanding of interfaces to be able to implement it how I want without a bit of help.

What I would like is for all buildings to implement an interface called Structure, which will contain all methods that would be common to all buildings. Then I would have more specific interfaces, such as Teleporter, Radar, Armament, Regenerator, etc. These interfaces would contain the methods specific to the buildings that would have such functionalities. For example, Armament would have a shoot() method. For the case of the JumpGate, it would implement Teleporter.

Is that the way to do it, or is there a better way?

From there, I would like to able to cycle through all buildings in an ArrayList, but be able to reference them with their specific functionalities.

What I would like is so that when I right-click near a JumpGate when I have ships selected, they would set that as there destination. I know how to do that. When the right-mouse button is pressed, I would cycle through all of the buildings on the selected ships' team, and find the nearest. If it is a JumpGate, and within say 100 pixels, then it would store that in a variable.

However, what type should the ArrayList be, so that I can then store the building as a JumpGate?

Another question - how can variables that are common to all buildings be declared only in one place? That would be much easier than declaring the same variables for every type of building.

Thanks for your help.

EDIT: After reading your post again, would the Structure interface contain every method of every type of building, and every type of structure would as well, but only fill the bodies of the required methods?
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!