views:

362

answers:

10

Hello,

Lately i decided to take a look at Java so i am still pretty new to it and also to the approach of OO programming, so i wanted to get some things straight before learning more, (i guess it's never to soon to start with good practices).

I am programming a little 2D game for now but i think my question applies to any non trivial project. For the simplicity i'll provide examples from my game.

I have different kinds of zombies, but they all have the same attributes (x, y, health, attack etc) so i wrote an interface Zombie which i implement by WalkingZombie, RunningZombie TeleportingZombie etc. Is this the best thing to do? Am i better of with an abstract class? Or with a super class? (I am not planning to partially implement functions - therefor my choice for an interface instead of an abstract class)

I have one class describing the main character (Survivor) and since it is pretty big i wanted to write an interface with the different functions, so that i can easily see and share the structure of it. Is it good practice? Or is it simply a waste of space and time?

I hope this question will not be rated as subjective because i thought that experienced programmers won't disagree about this kind of topic since the use of interfaces / super classes / abstract classes follows logical rules and is thereby not simply a personal choice.

Thank you for your time

-Samuel

A: 

I don't think that in your case your interface and class structure aligns well with the reality. In fact, I believe (correct me if I'm wrong) that each zombie can be walking, running, teleporting etc. depending on where it is.

Therefore, you should have a zombie class or interface and have actions which modify the zombie's state. The action would probably be an interface or an abstract class, so that you can apply any action to a zombie without knowing what the exact action does (e.g. action.perform(zobie)).

If you have different kinds of zombies, such as three-legged-zombie and one-armed zombies, you might want to implement different classes which handle the zombie stuff, such as displaying themselfes or validating state changes (e.g. a special kind of zombie may not accept to be teleported).

Lucero
It would be an interesting sociological question to see how likely someone was to interpret 'walking' 'running' and 'teleporting' as states rather than types plotted against how many hours of their life have been lost to cheap zombie shooter games :)
Affe
Why i had the different types is because they have different approaches of 1. Moving and 2. initialization, while walking zombies walk into the screen teleporting zombies appear near you and attack you. There might also be a drunk Zombie randomly running around at high speed throwing bottles (example)
Samuel
I see, so they *are* distinct zombie types and not actions which can be performed by any zombie. In this case having their own implementations would be fine IMHO.
Lucero
+4  A: 

You can think of an interface as a "contract". You are defining a set of methods that classes which implement this interface must implement.

An abstract class, on the other hand, is used when you have some code that could be common to all the child classes you want to implement. So you might have an abstract class called Shape that has some common code, and in your derived classes (Circle, Square, etc.) you could have the code that is specific to those shapes (getArea would be an example). But something like color might be common to all shapes, so you could put a getColor method in your Shape abstract class.

And you can combine the two ideas. You can have abstract classes which implement interfaces, and this gives you the best of both worlds.

These concepts are used over and over again in OO, so it's important to understand them. You seem to be well on your way :).

So if your zombie class has some common behavior that applies to all types of zombies, it sounds like a good candidate to be an abstract class. You could also consider creating an interface (maybe a GameCharacter interface) if you have other characters in your game (maybe UndeadMice or something :)). Then your Zombie abstract class and UndeadMouse abstract class would implement the GameCharacter interface.

dcp
+1 for using "contract"
Lerxst
Thank you :) It was difficult to decide who to give the 'answered' though..I especially like your idea about Abstract classes implementing the interface, provides a very clear structure of types with roughly the same properties while allowing very different types of movement handling for example. Still having a hard time to really connect everything the right way seeing all the relations etc
Samuel
@Samuel - When you have problems seeing how to connect things, it sometimes helps to draw the stuff out on paper, or use some tool like Microsoft Visio. It can help you visualize how things fit together so you can design the proper level of abstraction.
dcp
A: 

in terms of your Zombie example, the interface will do well, unless you have common code that you want all zombies to do.

Say you have a Move method, that makes walkingzombies walk, runningzombies run, etc. However, if you want "Move" to make any kind of zombie do something common, then the interface is going to force you to duplicate code, as you cant put a body in an interface.

Lerxst
A: 

I would have written Zombie as an abstract class to avoid the redefinition of the fields x, y, health, etc...

For the Survivor class, I would simply have declare public the functions to be used externally. I declare public functions at the top of the class. Declaring an interface when there is only one class implementing it uselessly adds a file to maintain. Avoid it.

Maurice Perry
I wouldn't call adding one file a maintenance problem. Later when you'd want that extra something which you'd get with an interface but you don't have one and it's a lot of work to put one in, that's a problem.
JHollanti
One file is not a problem, but if you do this systematically you will end up with lots of them. Adding an interface when needed is no big deal with today's IDE's.
Maurice Perry
For me the interface files also help me keeping the structure of the whole program clear. Good point with the x, y, health, i'll probably use the idea mentioned above of implementing the interface with abstract classes for Zombies who'd have a common x, y, Health.
Samuel
A: 

Nobody agrees about the use of interfaces over super/abstract classes ;)

The main reason to use interfaces and super/abstract classes is to enable polymorphism. In your case for instance, you have stuff moving on the screen (the player and the zombies and so on). Why not make them all move on the screen using the same method? Maybe inherit everything that's going to move on the screen from an object called "Movable" or something like that.

And if you're really into this stuff you might want to look at mixins as well. It's not something that Java supports directly but there are libraries built for it.

JHollanti
@JHollanti: Joshua Bloch, the guys behind the Spring framework and basically anyone who doesn't want to get locked into single-(implementation)-inheritance all favor composition over (implementation) inheritance. That's quite a lot of people :)
Webinator
Granted, a good point, but i'm not going to start discussing the subject ;) Not enough time in the world.
JHollanti
@JHollanti: for common behavior, use the strategy pattern instead. Let the interface zombie have a getMoveStrategy() method and call it using zombie.getMoveStrategy().move(). There might be a HopStrategy, a SlouchStrategy a RunStrategy etc. which could have parameters (e.g. a wounded Zombie is slower, an angry Zombie is faster etc., there's a lot of if-then-else involved without the strategy pattern)
seanizer
A: 

Yes, I think you're heading down the right track with interfaces over abstract classes.

Any concrete Zombie you might want to make could possess any combination of the Walking, Running or Teleporting features you care to implement.

I think modern programming theory discourages inheritance as much as possible, because it inhibits reusability and flexibility in the long-run. Rather, use interfaces and composition to achieve flexibility without 'tight coupling'.

One methodology to re-use code without inheritance, you could apply the 'Favour composition over inheritance' paradigm.

I like to think Josh Bloch's 'Effective Java' (2nd edition) can be taken as "current thinking" ...

http://books.google.com/books?id=ZZOiqZQIbRMC&pg=RA1-PA71&lpg=RA1-PA71&dq=%22Bloch%22+%22Effective+java:+programming+language+guide%22+&hl=de&sig=RxlDlRBWUvNAzsAFzqOcftrYI5E#v=onepage&q&f=false

So, you could implement all your behaviours as independent classes, and then give each zombie implementation its own combination of behaviours, through implementation & composition..

Hope that makes sense & helps ...

amir75
yes, but what if all zombies should do something common when they move? They would all have to have duplicated code, wouldnt they?
Lerxst
@Lerxst: no, that's the point of composition. You'd simply "wrap" an instance of a class representing the common functionality and delegates the common calls to that class. The only duplicated code would be the delegation calls but that's one line per method (in each of your *XXXZombie* class). Delegating calls to a wrapped subject can be done automatically by good IDEs.
Webinator
amir75
Lerxst
You're probably right, it's sometimes not worth bothering with compostion until you really need that flexibility. I still tend to use inheritance whenever I reckon I'll only use some functionality once and exclusively within one class heirarchy.Still, I think composition's a good tool to have in your pocket whenever you find inheritance is blocking your progress. All the best
amir75
@Lerxst: those who advocate abstract classes would want to make you believe it's about preferences. But it really ain't. You're shooting yourself in the foot when you rely on "code reuse"/abstract-classes, even if you don't see it. You'll have issues unit testing (harder to mock). You'll have less OO code (hello single-implementation-inheritance, which doesn't exist at the OOA/OOD level) and you'll have unexpected issues, like the one here: http://java.sun.com/developer/technicalArticles/javase/finalization/ (that article advice composition over inheritance where you'd least expect it).
Webinator
@Wizard personally, I use interfaces all the time, and I havent really used abstracts in any major projects to date, so i agree with you, I was just looking at the specific example and it seemed to fit.
Lerxst
amir75
+1  A: 

When in doubt, I choose to follow the GOF paradigm.

Encapsulate what varies: - Define unique behavior in its own class. To refer the above example, implement behaviors for walking, running and teleportation in its separate class. This way, polymorphic behavior is implemented.

Conversely, **Aggregate what is common** - Use Abstract classes to define common behavior in polymorphic associations. I use these principles when designing relationships between objects.

Kartik
A: 

I have different kinds of zombies, but they all have the same attributes (x, y, health, attack etc) so i wrote an interface Zombie which i implement by WalkingZombie, RunningZombie TeleportingZombie etc. Is this the best thing to do? Am i better of with an abstract class? Or with a super class?

an abstract class will be a super class for your zombies. an interface would also in some sense be a super class (super interface?) for your zombies.

the common properties suggest at least an abstract base class for common properties.

(I am not planning to partially implement functions - therefor my choice for an interface instead of an abstract class)

not sure what you mean by this.

if you had different kinds of monsters (goblins, orcs, etc.) you might find behaviour common to these that would want to belong to different base classes. this would suggest an interface.

i would start with an abstract base class and see what the code tells you as you write it.

I have one class describing the main character (Survivor) and since it is pretty big i wanted to write an interface with the different functions, so that i can easily see and share the structure of it. Is it good practice? Or is it simply a waste of space and time?

your survivor is what is called a player-character (as opposed to a non-player character - someone in a game who will normally not attack your survivor).

most games treat all of these character types as some kind of monster since they will all have many properties in common (health. magic, treasures, weapons, etc.)

so perhaps that's more of an argument for an interface.

see:

http://stackoverflow.com/questions/2768748/using-inheritance-and-polymorphism-to-solve-a-common-game-problem http://stackoverflow.com/questions/1212149/class-diagram-examples-for-rpg-role-playing-game http://stackoverflow.com/questions/2123071/designing-class-hierarchy-for-typical-characters-in-role-playing-game

Ray Tayek
A: 

My opinion is you better use abstract class called Creature as a super class for all type of, well, creatures, and extend it to Zombie for all type of zombies.
And you will also need an interface.. to define what are the things that a creature can do..
like maybe, walk, or claw, or scream...
the reason why you need an abstract class is to disable the instantiation of Creature, you wouldn't want to have a creature without knowing what creature it is, right?

p01ntbl4nk
technical point: if you want to disable instantiation, abstract isn't enough, you also have to make the constructors protected, otherwise anonymous instantiation like this: new Creature(){}; is possible.
seanizer
A: 

You had better read Head first design patterns. That answers all your questions like this.

Hemanth