Jump to content
  • Advertisement
Sign in to follow this  
abeylin

[java] what's the correct way to create classes/interfaces

This topic is 4839 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I am stumbling before I start programming. Lets say I want to have the following scenario in a 2d game. A person can become a swordsman, and a swordsman can become either a red knight or a black knight. What should the names of the classes/interfaces be. For example: Interface Character, it has declares methods to preload all images, get size of current image, turn the character left/right/degrees?/etc., get current image of character, maybe some others... Abstract class mammal, that can run, walk, jump, etc. (as opposed to fish, which is still a character, but can't walk) I am just not sure where to stop making interfaces, abstract classes and start writing classes. Unless I like the response, i think I will start coding backwards. Start with class BlackKnight. Whatever methods are shared between BlackKnight and WhiteKnight, move into one class, from which those subclass. Than write Swordsman, which probably means steal some methods from Knight class (though not all - such as blockWithShield() -- Swordsman doesn't have shield) Please let me know how to correctly structure the interfaces/abstract classes/classes. I am a C programmer at heart, and find this a bit confusing. Thanks for your help

Share this post


Link to post
Share on other sites
Advertisement
It depends on what you intent is. If Person is a playable type, then it gets a class. If it's just something for the backend of the game, and nothing the player should worry about, then it should be either an interface or an abstract. If it's made up entirely of methods for interfacing, then it's an interface. If you want it to be an actual class(with variables and such), that just can't be instanced, abstract. The same goes for swordsman, and the two knights.

It can be tricky at first, but once you learn the logic behind each of them it gets easier.

(PS, mixing top-down, and bottom-up design is a common approach to designing.)

Share this post


Link to post
Share on other sites
Whoah, whoah, whoah. What you described above is incredibly overkill. Huge inheritance heiarchies are almost always unnecessary.

Share this post


Link to post
Share on other sites
This is something that becomes more intuitive with time. When you first start out, you identify new classes and interfaces everywhere. It might seem natural to have classes such as Mammal, Reptile, or Primate derive from a common Character class. In reality, it's usually not the best solution. The reasons will become clear with experience.

The key is to understand the ddifference between what really needs to be a class unto itself and what can be implemented as a class instance. As an example, consider a car class. Perhaps you want to have 2-door and 4-door cars. A naive design might look like this:


class Car
{
}

class FourDoorCar extends Car
{
}

class TwoDoorCar extends Car
{
}




Should you also be subclassing car with a SportsCar class? What about a LuxuryCar class? How can you have a LuxuryCar with two doors?

Often, the only thing that differentiates the objects that you envision is their properties. All cars have doors, engines, wheels, models, makes, and prices. In this case, the problem is best solved with a single Car class that includes fields for numDoors, make, model, etc... This gives you much more flexibility. Your example of swordsman, red knight, and black knight fit this well. These are all examples of professions. In my mind, you would have a Profession class and each profession would be an instance of the class (as opposed to a subclass). Each Person would have a member variable that is a Profession instance, and you can easily change a person's profession at any time.

Regarding interfaces, try not to make something an interface unless it is okay for any object to implement it. Interfaces are a way for an object to advertise that it exposes certain methods according to a specific contract, but it also means that any object under the sun can do so. Think about the Character interface you described. Imagine you had a MapLoader class in your program, the function of which is to load a world map from disk. Would it be okay for the MapLoader to implement the Character interface? Perhaps that's a bit farfetched, but what about a building in the game - can it also be a character? These are the sort of questions you need to answer when deciding what should be an interface and what should be a class. If you can see a use for multiple unrelated[/] class types to implement the same functionality, you have an interface. But if you only see a narrow subset of your classes implementing functionality which is related in some way, you have a base class instead (which need not always be abstract). Your Character interface is a good example of something that shouldn't be an interface, but a class instead. Perhaps it's a subclass of an Entity (or Actor) class, which is also the parent of all objects in the game (items, buildings, particle effects, audio emitters, etc...).

Names generally should be descriptive enough that they give a clear indication of what the basic function of the class or interface is. Other than that, don't stress over them too much. As long as you aren't doing silly things like calling a map loading class BobBarker, just use common sense.

Share this post


Link to post
Share on other sites
I think for a 1st, 2nd or even 3rd time at writing good OOP/OOD you should probably go with your intuition: 'start with a Red Knight', and just work sort of backward. Yes you will probably waste some time, but oh well its a learning curve thing. Besides each application is going to be little different. You should refactor at will too -- its not like you have deadlines right?

Comment on the above design: I think it would be alright to delegate the loading of images, that is to say encapsulate a class/object that can handle the loading of images, and then maybe put a method of something like: getImageLoader() and setImageLoader() in an interface that all graphic entities need to supply. And so you have a contract then with all entities that must either create their own ImageLoader object, or be assigned an image loader object.

Some other methods for the super class(es) (note that the design might find itself with 1, 2 or more super classes). I personally feel that at more than 4 super classes is pushing it. But each situation is different.


class NumberredEntity implements Serializable {
setID();
getID();
equals();
}

class abstract MovableEntity
extends NumberredEntity
implements MovableIF
{
moveTo(x,y)
setModel();
getModel();
abstract update(); // called each loop cycle
}

class abstract WarringGraphicEntity
extends MovableEntity
{
// provides stuff like health, equipment, good/evil, etc.
// possibly place a class between MovableEntity, and WarringGraphicEntity
// like simply GraphicEntity, followed by WarringEntity.
renderEntity();
}

class RedKnight
extends MovableEntity
{
// finally specific to a certain type of entity,
}







Something like that -- but actually I'm not really sure I like that design either. Just a thought. Just have fun.

Edit: Lately I have been delegating the renderrring to an Object that is tailor made for each entity -- I don't know if this is something I like or not just yet. So each delegate class requires information from the class it is about to render...there's probably a better way.

L-

[Edited by - Lucidquiet on August 15, 2005 2:35:09 PM]

Share this post


Link to post
Share on other sites
I have also started doing the following in design (just something to either get comments on from someone else reading this thread, and to give you something to think about during design) as patterns/rule's of thumb that I have began to use:

No static methods (if it is possible to avoid -- which generally means not using the typical perscribed method for Singleton classes, or Singletons at all.) Besideds it causes a strange sort of binding/dependency througout the entire code base. Exception: random utils.

No class field (ie. class level static member fields) Can't serialize them the ussual way, and generally is a sign of design that could use improvement.

Default Constructor All classes have "ONLY" a default constructor. This requires that somethings that you would want to initialize in the constructor be set() via a method instead. This allows more flexibility later on down the road when you want to swap out something. Sometimes I forget to initialize things durring code testing, but then again its not terribly hard to find a NullPointerException in java from the stack trace. And in addition I end up providing a start/begin/initialize/whatever and then of course a reset/restart/reinitialize method(s). This is just something I'm toying with. I think it's working out OK so far.

L-

[Edited by - Lucidquiet on August 15, 2005 3:05:04 PM]

Share this post


Link to post
Share on other sites
I appreciate all of your input.

Interesting question has come up.
Is your profession what you are, or just what you do?
If your profession is what you do, than obviously Profession should be a class, and Person (or whatever) can create an instance of Profession, and set it to Swordsman.
Yet, if your profession is what you are, than you are an instance of a class.

For example, if you are a computer programmer. Than there should be a class ComputerProgrammer, and "abeylin" is the instance of it. But, if your profession is a computer programmer, than you can have a class Person, with instance "abeylin", and property "Profession" set to Profession.COMPUTER_PROGRAMMER.

So it all comes down to how you answer "tell me about your self". If you say that you are a computer programmer, than you are an instance of the ComputerProgrammer class. And if you say I work as a computer programmer, than that's your property.

Am I on track here?

Share this post


Link to post
Share on other sites
Quote:
Original post by abeylin
I appreciate all of your input.

Interesting question has come up.
Is your profession what you are, or just what you do?
If your profession is what you do, than obviously Profession should be a class, and Person (or whatever) can create an instance of Profession, and set it to Swordsman.
Yet, if your profession is what you are, than you are an instance of a class.


One of those nice on paper theories. That's fine for small projects, learning the ropes, etc... But when you start getting into the realm of real world software you will find that making every profession a class is the wrong way to go. Data driven development, where your profession data are loaded through external resources (XML files, databases, scripts, or what have you) is often the right choice for many projects, and is facilitated by a design where professions are instances.

OO design involves identifying the objects in your program and defining how they will interact. Many beginner level books teach this through analogy, pulling objects from real life and implementing examples in code. A neat learning tool, but not at all what actually happens. The sooner you learn to break with the real world analogies the better you'll be. Objects should be defined in the context of the program. A Person in your game is not the same as a Person in the real world, so you shouldn't think of a game Person in the context of the real world. A Person in the game is a GameObject, not a human, not a mammal, not something else. When you think that way, in the context of your game world and the subsytems that drive it, your designs can become much more pratical and focused, and much less of a philosopical debate.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Here's how I'd do it.

First remember that inheritance isn't always the best way of modelling things. Don't forget composition. When you are modeling roles a person plays, composition is the better choice than inheritance.

It also depends on how big and complicated game you are making; how much flexibility you need etc.

Anyway, one way could be like this:


interface Actor
{
// Role management.
addRole(ActorRole role);
removeRole(ActorRole role);
ArrayList getRoles();

// Actor management
PerformMainAction();
GetCurrentControlState();
}

interface ActorRole
{
// Actor management.
private Actor actor;
public Actor getActor();

// Role management.
public ArrayList getSkills();
}

public class BlackSmith implements ActorRole { ... }
public class BlackKnight implements ActorRole { ... }
public class Paladin implements ActorRole { ... }

public interface Action
{
perform()
}

public class Character implements Actor
{
public PerformMainAction() { roles[0].getMainAction().perform(); }
private name;
private ActorRole roles[];
}


So here Actor defines the interface an actor in a game. ActorRole is the interface implemented by all roles that an actor can have in a game. Thus actors can have more than one role and can switch roles. This is just a rough cut written in a minute so obviously it needs a lot of refinninf and a clearer task delegation, but I'm sure you get the idea.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!