• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Abstraction/OOP issues

 
Greenhorn
Posts: 29
1
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm somewhat new to Java - been doing the Univ of Helsinki on-line course for a couple of months - and I am totally baffled about how to design classes/architect a multi-class program.

I have a pretty good handle on the "rules" of how to implement interfaces, abstract classes, super & sub-classes, etc, but I am completely clueless as to the thought processes/design considerations that go into deciding how to put together evan a relatively simple program.

For example, if one has to create multiple objects of the same class and then access those objects, either individually or as a group, from a different class, what should be considered when deciding between an interface, abstract class, subclass, etc.  Is there any hard and fast rule (or even a general rule of thumb) about whether an object should be created within its class (I know the constructor actually does the creation, but when should the constructor be called?), created in Main, created in the class which manipulates the object - or something else?

I've had no serious problems with the procedural aspects of java, but the OOP/abstraction concepts are killing me!  I don't consider myself stupid, but I'm sure as heck befuddled, and would really benefit from an in-depth discussion of this.  Thanks very much.
 
Saloon Keeper
Posts: 10687
85
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I don't know if this is too simplistic for you at this point but I find this helps newbies.

When you examine your requirements, look for nouns. These will typically become classes. Look for relation ships between nouns, as in HAS-A vs. IS-A. A "Car" is-a "Vehicle", a "Car" has-a "SteeringWheel".  IS-A implies inheritance and HAS-A implies aggregation. Look for verbs, these tend to become methods. "Roll the dice" has a noun "dice" and a verb "roll".
 
Al Davis
Greenhorn
Posts: 29
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Carey,

Thanks for the rapid response.

I'm aware of "is-a" and "has-a" distinctions, but those concepts don't seem to always apply.  The exercise I'm working on now is to design a simple game - a dungeon filled with vampires.  The player must move to the vampires to kill them and has X moves to do so before his flashlight dies and the vamps kill him/her.  The dungeon is represented by a rectangular grid of dots; the player has a unique symbol replacing a dot at his location, as do the vamps.  Each time the player moves (as many steps as he wants), the vamps move randomly by the same amount.  At present, I'm trying to set it up with separate Dungeon, Player and Vampire classes, along with a user interface class and maybe some other "helper" classes.  I expect that most of the actual game play code will be in the Dungeon class, although I suppose it could occur in the UserInterface class.  I've already written and trashed code for the classes twice and would really like to get a firm conceptualization of how to design the structure before I proceed again.

The dungeon contains the vampires and the player, obviously, but I'm not sure this qualifies as a "has-a" relationship and, if it does, I don't know how that matters.  The vamps can be aggregated at the start of the game, when they are created, but each starts at a different random location and then each moves independently of the others and the player as the game progresses.

It seems an interface would be useful in terms of allowing access, for example, to the vamps (and the player) from withing the dungeon class, but I don't understand how to determine what method(s) should be specified in the interface, and I'm uncertain as to how to use the interface - as a reference variable "type" statement, as a method parameter, or whatever.  As I mentioned above, the thought processes for these decisions are simply unfathomable to me at this point.

Again, thanks for your response.  I look forward to more.
 
Carey Brown
Saloon Keeper
Posts: 10687
85
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
There seems to be overlap between a Player and a Vampire. You could have an abstract Piece class that both Player and Vampire extend. A Piece has-an X,Y coordinate, an icon, and can move(...). A player has a (flashlight) count down of the number of moves.

For instance.
 
Sheriff
Posts: 7125
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Welcome to the Ranch!

You're going in the right direction.  A Dungeon HAS-A Player and several Vampire(s).  Players need a way to enter their moves, so you can create an enterMove() method, or split it up so that one class does the displaying and the other gets and validates the move.  A Vampire need to move (randomly) but it also needs to to tell if the move is valid.  Ah! You have two different classes needing the same functionality.  So create a class the has a validateMove() method.  You need a class to start the game and keep going until the game stops, either by a Player killing a Vampire or vice versa.  This kind of class is often called Main.  The Dungeon class need to have a grid to play on, x number of Vampire(s), and a Player.

I tried above to give you a bit of the thought process that coders often go through.  Does it make sense?
 
Carey Brown
Saloon Keeper
Posts: 10687
85
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
A "has-a" relationship can be bi-directional. A Dungeon has-a grid of pieces. A Piece has-a Dungeon that it resides in. A Dungeon can draw itself and in doing so can iterate over the grid of Pieces and call upon each Piece to draw itself.

I'm less clear on the intent of your UserInterface.
 
Al Davis
Greenhorn
Posts: 29
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
To All,

Thank you for your comments.  They are helpful.

The Player and the Vamps do have a lot in common. In each game turn, the player issues one or more move commands (Up, Down, Left, Right - one "step" per command) to the player object, which then follows those directions.  Move validity isn't explicitly required in the specs, but it is obviously implied.  After the player has moved, each of the Vamps moves in a random direction, the same number of steps the player took in his move.  The specs do explicitly require validity checking to prevent the Vamps from moving off the board, and only one Vamp can occupy a given space.  If the player moves into a Vamps' space, the Vamp is killed.  After the Vamps move, a new turn begins.

I do have a Main class.  I've done enough practice that I kind of take it for granted, so didn't mention it.  In my initial attempts at this, I built an interface with a Move() method, but I'm having difficulty figuring out how to best use this.  Should I simply consider it as a way to cut across class boundaries to get to various methods, or should there/could there be more to it?  The intent of the UserInterface class is, at least, to get the user input for the player's move.  It could also be a reasonable location for validating the move and, again, the Move interface might allow me to access it from the Dungeon class.  Anyone have a better idea?

Now - this may be the core question I have.  Assuming I build an interface(Move or otherwise), how do I know how to use it?  I'm not entirely clear on the concept of passing it as a method parameter, nor on using it as a variable or "new" object Type.  I know these things -can- be done, but I don't understand -why- they're done.  Guidance would be greatly appreciated.

Thanks.
 
Knute Snortum
Sheriff
Posts: 7125
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Let me address the interface/inheritance question first.  It's complex, but I'll simplify it somewhat.

Let's say you decide that both Player and Vampire have qualities or behaviors in common.  You have three choices: use an Interface or an Abstract class or a full-fledged class.  The difference between these is getting fuzzier, but basically a class can implement many Interfaces but only extend one class, Abstract or not.  Say you notice that both Player and Vampire have a common action: move.  If you use an Interface, it might look like this:
Now if both Player and Vampire implement Movable, then would have to override the move() method, and it would have to have two parameters, both ints, and a return value DungeonGrid. Now since you can guarantee that classes have a common method, you can do something like this:
Now the above code is kind of nonsense, but hopefully you get the idea.  So an Interface is how you give a class a quality or functionality that will be difference in every class that implements it.  A real world example is that List is an interface and classes like ArrayList and LinkedList implement this interface.  That's why it's recommended that you declare a List like this:
Now if you want to change the ArrayList to a LinkedList, you only change one line.

But what if decide that both a Player and a Vampire are a Piece.  Then you would declare a class, abstract or not, and both Player and Vampire would extend it.  If the move() method is identical in Player and Vampire, the method would be declared non-abstract in Piece and Player and Vampire could just call move() without overriding it.

So if two or more classes have a common quality or behavior, usually use an Interface and implement it.  If the behavior needs to be different is each class, use an abstract method.  If a class is another class, then use an abstract or non-abstract class to extend the first class.

If you really want to dive into this, look at this URL:

https://docs.oracle.com/javase/tutorial/java/IandI/index.html
 
Al Davis
Greenhorn
Posts: 29
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you.

I looked at the Java tutorials info (I've seen it before) and am frustrated because it has 5 or so screens of info about -how- to write and implement an interface, but very little about -why- to do so.  Maybe I'm overthinking the problem, but I'm not impressed with simply being able to reuse a defined method, especially since you have to overwrite it in code, anyway.  It's good to be able to access objects which implement the Interface across class boundaries, but is that all there is?  Is that an interface's primary (or sole) purpose?  I keep waiting for a light to go off in my head about some "gee whiz" aspect of Interfaces, but it ain't happening and I'm getting frustrated.
 
Knute Snortum
Sheriff
Posts: 7125
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Okay, let me give you a real life example of when I used an interface.

I have a demo of how to do multiple screens in JavaFX using FXML files. I hold all the info about the FXML files in a Map.  When I need to display an FXML file, I get it from the Map.  Each FXML file holds its own controller class.  This class needs a reference to its stage to be injected.

Now the problem is that I have all these controllers, which are all different classes, but I need to know they all have the behavior of being able to set a stage (from the FXML).  How do I set a stage in all these different classes?

I use the interface Stageable.  It's very short:
Now all my controllers can implement Stageable so I can do this:
Does this make sense?  The interface Stageable creates a type that I can use to guarantee that the method setStage() will be there.

If you want to look at the project in the wild, click:

https://github.com/ksnortum/javafx-multi-scene-fxml
 
Al Davis
Greenhorn
Posts: 29
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I understand what you're doing re: using Stageable to give the controllers access to the stage info, but is it necessary that the controller be a Stageable type?  Since you've implemented Stageable in the controllers, wouldn't the be able to get the stage info regardless of what Type they are, via the setStage() method in Controller?
 
Ranch Hand
Posts: 91
Netbeans IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Al Davis wrote:I looked at the Java tutorials info (I've seen it before) and am frustrated because it has 5 or so screens of info about -how- to write and implement an interface, but very little about -why- to do so.  Maybe I'm overthinking the problem, but I'm not impressed with simply being able to reuse a defined method, especially since you have to overwrite it in code, anyway.  It's good to be able to access objects which implement the Interface across class boundaries, but is that all there is?  Is that an interface's primary (or sole) purpose?  I keep waiting for a light to go off in my head about some "gee whiz" aspect of Interfaces, but it ain't happening and I'm getting frustrated.



Hello Al,

A Java interface is Java's way to partially implement multiple inheritance, which is not officially a Java feature.

Multiple inheritance as a background concept (again, not allowed in Java) will help you understand the
purpose of the Java interface.
 
Carey Brown
Saloon Keeper
Posts: 10687
85
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
True multiple inheritance suffers from the "diamond" problem. If you have parent class "P", and P has two classes, "A" and "B" that extend P, then each of A and B will inherit the data and behaviors of P. The problem comes when you want a new child "C" that extends both A and B (which Java doesn't let you do). A has P's data therefore C has A's data as well as P's data AND C has B's data as well as P's data; PROBLEM! What rule would govern if you have P's data twice, once via A and again via B? You could think of potential rules for this but they are all fraught with issues. This is why Java chose not to permit multiple inheritance.

This is called the "diamond" problem because if you draw the inheritance diagram for this simple example it takes the shape of a diamond.

Java's answer is the interface.
 
Al Davis
Greenhorn
Posts: 29
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
First, I made  dumb statement about using the setStage() method to get the stage info in Knute Snortum's JFX program.  My bad.  But I'm still not sure why using Stageable as a Type is necessary.

Next,  I'm aware of the diamond inheritance problem but haven't paid much attention to it. I don't write any C++ or code in other languages which allow multiple inheritance, and I'm confused enough as it is just dealing w/ Java!  I try to choose my headaches carefully.

But I want to return to a question I asked a few posts ago - "It's good to be able to access objects which implement the Interface across class boundaries, but is that all there is?  Is that an interface's primary (or sole) purpose?"

Thanks to everyone.
 
Marshal
Posts: 28177
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Al Davis wrote:But I want to return to a question I asked a few posts ago - "It's good to be able to access objects which implement the Interface across class boundaries, but is that all there is?  Is that an interface's primary (or sole) purpose?"



No. At least, objects can naturally be accessed "across class boundaries", as you put it, because otherwise it would be impossible to use more than one class in an application. That has nothing to do with interfaces.

The purpose of an interface is to say "My design thinks that it would be useful to be able to identify classes which have this set of features." (The "features" would correspond to methods.) Of course it's possible to create a class with those features, and often that is what happens. Then you can continue by designing subclasses, which of course also have those features and can have others. But other times you want to have several classes which have that set of features, but having that set of features isn't primarily how they are related. Indeed they might be completely unrelated except that they need those features. In this case an interface could be preferable.

Perhaps you're like me and you feel better when you see an example of such hand-waving. So consider the interface Closeable from the standard API, which just has a public void close() method. It turns out that a lot of different classes need that feature, but that isn't primarily what those classes are for. But on the other hand it also turns out that there are situations where it's necessary to close an object, but you don't know anything else about that object. So creating a Closeable class for those things to subclass is bad, because those things might need to be subclasses of something else of which you know nothing. So that's why it's an interface.
 
Knute Snortum
Sheriff
Posts: 7125
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

But I'm still not sure why using Stageable as a Type is necessary.  


Think of it this way: I have a List called controllers, containing all different classes.  I want to get the first one and call its setStage() method.  So I start typing...
But wait, what is xxx?  Let's say that the first class in the List is Controller1.  I could write
But that's not going to work for indices 1, 2, etc.  So I make an interface Stageable and implement it in all the controllers. Now I can write:

 
Al Davis
Greenhorn
Posts: 29
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Paul and Knute,

Excellent responses.  Thank you.  Interfaces are finally starting to make at least a little sense to me; the trick now is to see if I can work through a design and use them properly.  Thank you very much.

Al
 
Marshal
Posts: 8856
637
Mac OS X VI Editor BSD Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Al Davis,

Cowgratulations, your topic has been picked to be published in CodeRanch's August journal.
 
Rancher
Posts: 285
14
Eclipse IDE C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Knute Snortum wrote:

But I'm still not sure why using Stageable as a Type is necessary.  


Think of it this way: I have a List called controllers, containing all different classes.  I want to get the first one and call its setStage() method.  So I start typing...
But wait, what is xxx?  Let's say that the first class in the List is Controller1.  I could write
But that's not going to work for indices 1, 2, etc.  So I make an interface Stageable and implement it in all the controllers. Now I can write:



Controller1 controller = controllers.get(0); // its only index 0
Stageable controller = controllers.get(0); // also only index 0

How does this work??? I don't get it.
 
Ranch Hand
Posts: 393
9
Open BSD BSD Debian
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Al Davis wrote:I'm somewhat new to Java - been doing the Univ of Helsinki on-line course for a couple of months - and I am totally baffled about how to design classes/architect a multi-class program.

I have a pretty good handle on the "rules" of how to implement interfaces, abstract classes, super & sub-classes, etc, but I am completely clueless as to the thought processes/design considerations that go into deciding how to put together evan a relatively simple program.

...



Take a look in
The Object-Oriented Thought Process, by Matt Weisfeld
surely can help in some manner
 
Knute Snortum
Sheriff
Posts: 7125
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

S Fox wrote:Controller1 controller = controllers.get(0); // its only index 0
Stageable controller = controllers.get(0); // also only index 0

How does this work??? I don't get it.


Don't focus on the .get(0) part; that's not important.  The point is when you try to access any element in the list you don't know whether it's Controller1, 2, or 3.

Here's a (quite possibly overblown) example.  I wanted to make it compilable so you can play with it to maybe understand better.  The run() method is the one to look at.
reply
    Bookmark Topic Watch Topic
  • New Topic