Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411581 Posts in 69386 Topics- by 58445 Members - Latest Member: Mansreign

May 05, 2024, 07:10:17 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Java Inheritance Question
Pages: [1]
Print
Author Topic: Java Inheritance Question  (Read 1489 times)
Loren Schmidt
Level 10
*****



View Profile WWW
« on: July 06, 2009, 03:06:05 PM »

I'm mid-way through doing the engine work for an RPG I'm working on, and I have a question about inheritance in Java.

There's a base Action class. When an action resolves, the use() method is called, which calls getConfirmMessage() to get a string to send to the console. The various different character actions are subclasses of the base action class. They all have their own getConfirmMessage() method, which has an action specific message in it. They all use the same use() method. however.

The problem is that if I call super.use(), it gets the confirmation message from the base class instead of the overridden version. Is it true that in Java, in the context of a super.use() all other methods are rolled back to the base version as well? I'm used to ActionScript, which seems to handle this differently (overridden versions are used instead of base versions). I think I'll work around this by storing the message in a String instead (and overwriting in in the constructor), but I'm curious about how the language works. Any clarification would be appreciated.
Logged
Colonel Mustard
Level 0
**


View Profile
« Reply #1 on: July 06, 2009, 03:16:33 PM »

I don't quite understand your setup, does it look like this?:

Code:
Action
{
   use()
   getConfirmMessage()
}

Handshake extends Action
{
   override getConfirmMessage()
}

And you want the use that's derived from the base class to get the result from the overriden getConfirmMessage in the derived class?
Logged
Impossible
Level 3
***



View Profile
« Reply #2 on: July 06, 2009, 03:20:49 PM »

I'm by no means a Java expert, but it seems like you simply want to call "use" from the derived class instead of "super.use" in this case.
Logged
Colonel Mustard
Level 0
**


View Profile
« Reply #3 on: July 06, 2009, 03:23:28 PM »

Oh right, it's been too long since I used java, forgot that super is actually a keyword. Any methods in the base class is transferred to the derived class, so if you've got something like this (with the setup I previously wrote):

Code:
Action one = new Action();
Handshake two = new Handshake();
Action three = new Handshake();

one.Use();
two.Use();
three.Use();

All but the first one will use the confirmation message from the derived class.
Logged
Overkill
Level 3
***


Andrew G. Crowell


View Profile WWW
« Reply #4 on: July 06, 2009, 03:29:30 PM »

I'm mid-way through doing the engine work for an RPG I'm working on, and I have a question about inheritance in Java.

There's a base Action class. When an action resolves, the use() method is called, which calls getConfirmMessage() to get a string to send to the console. The various different character actions are subclasses of the base action class. They all have their own getConfirmMessage() method, which has an action specific message in it. They all use the same use() method. however.

The problem is that if I call super.use(), it gets the confirmation message from the base class instead of the overridden version. Is it true that in Java, in the context of a super.use() all other methods are rolled back to the base version as well? I'm used to ActionScript, which seems to handle this differently (overridden versions are used instead of base versions). I think I'll work around this by storing the message in a String instead (and overwriting in in the constructor), but I'm curious about how the language works. Any clarification would be appreciated.

super is a keyword meaning the parent class of the element. Calling super.method() will always call the parent's method by definition (unless the parent is abstract, in which case your class is implementing that method). You should ONLY use super in the cases you need to access a parent class, which only arises when there are methods that have been overriden AND you need to call the parent's specific code. Really, this is a bad thing to do anyways, if you can help it.

By default calling any method foo(), Java will always use the overriden method. Yep.

« Last Edit: July 06, 2009, 03:38:43 PM by Overkill » Logged

Loren Schmidt
Level 10
*****



View Profile WWW
« Reply #5 on: July 06, 2009, 07:41:08 PM »

super is a keyword meaning the parent class of the element. Calling super.method() will always call the parent's method by definition (unless the parent is abstract, in which case your class is implementing that method). You should ONLY use super in the cases you need to access a parent class, which only arises when there are methods that have been overriden AND you need to call the parent's specific code. Really, this is a bad thing to do anyways, if you can help it.
I think I went about this wrong. What I'd like to do is have a single piece of funcionality in a single centralized location, then tack on bits of subclass specific functionality. So it looks like I made a poor assumption at some point, thanks. Because this is a simple situation, I'm leaning toward just using a variable for the message text, rather than having a getConfirmationMessage method. So the classes would look like this:
Code:
Action {
   String confirmationMessage = "Base class's confirmation message";

   public Action() {
      // base constructor
   }

   public void use() {
      Do message setup
      Pass "confirmationMessage" to message console
   }
}

Handshake extends Action {
   public Handshake() {
      super();
      confirmationMessage = "Handshake confirmation message";
   }
}
Logged
mcc
Level 10
*****


glitch


View Profile WWW
« Reply #6 on: July 06, 2009, 10:31:11 PM »

If you plan to have the subclass structure already, I think using a method is better in this case than using a variable. What if you have a class where the confirmation message turns out to be dynamic?

Methods in Java are by default "virtual", which means that if you are in Action::use() and you call Action::confirmationMessage(), it will call the version of confirmationMessage associated with the object's actual class-- NOT associated with Action (unless it's actually an Action object). In C++ or C# you have to specifically request a method be virtual, in Java EVERYTHING is virtual unless you request otherwise (using "final"). If confirmationMessage is acting non-virtual (ie is calling the base-class version rather than the derived-class version) then some sort of mistake has been made. Can you post the code that wasn't working?
Logged

My projects:<br />Games: Jumpman Retro-futuristic platforming iJumpman iPhone version Drumcircle PC+smartphone music toy<br />More: RUN HELLO
Movius
Guest
« Reply #7 on: July 07, 2009, 03:03:34 AM »

super is a keyword meaning the parent class of the element. Calling super.method() will always call the parent's method by definition (unless the parent is abstract, in which case your class is implementing that method). You should ONLY use super in the cases you need to access a parent class, which only arises when there are methods that have been overriden AND you need to call the parent's specific code. Really, this is a bad thing to do anyways, if you can help it.
I think I went about this wrong. What I'd like to do is have a single piece of funcionality in a single centralized location, then tack on bits of subclass specific functionality. So it looks like I made a poor assumption at some point, thanks. Because this is a simple situation, I'm leaning toward just using a variable for the message text, rather than having a getConfirmationMessage method. So the classes would look like this:
Code:
Action {
   String confirmationMessage = "Base class's confirmation message";

   public Action() {
      // base constructor
   }

   public void use() {
      Do message setup
      Pass "confirmationMessage" to message console
   }
}

Handshake extends Action {
   public Handshake() {
      super();
      confirmationMessage = "Handshake confirmation message";
   }
}
pretty certain confirmationMessage has to be protected in Action
Logged
Loren Schmidt
Level 10
*****



View Profile WWW
« Reply #8 on: July 07, 2009, 07:23:15 PM »

Yes, you're right, it would have had to be protected, I didn't catch that.

Thanks for the help, folks. I ended up coming up with exactly the same question in a different context, but this time I knew what the answer was. Hand Thumbs Up Left There is a base Entity class from which Creature and Item are both derived. It has the following methods:
Code:
	public void damage(int damage, Shared.DamageType type) { 
// consider ranged vs. melee, also using some set of constants for damage type
integrity -= damage;
if (integrity <= 0) {
integrity = 0;
destroy();
}
}


protected void destroy() {
// Remove from entity manager
// Leave things like debris or a corpse as appropriate
GameFlow.getInstance().getMessageLog().post(
"Entity destroyed.");
}

Creatures and Items are both handled by separate managers, so they override the destroy method and remove themselves from the appropriate manager. Thanks to some of the explanations I received earlier, I was able to work it out so that the Creature class could call super.damage() within its damage method, and still use the appropriate destroy method (that within Creature, not Entity):
Code:
	public void damage(int damage, Shared.DamageType type) { 
// Armor reduces sharp damage
if (armored) {
if (type == Shared.DamageType.SHARP) {
damage = (int) (damage * Shared.DAMAGE_RESISTANCE);
}
if (armor != null) {
// If we're wearing armor (as opposed to natural armor)
int armorDamage = (int) (Shared.ARMOR_DAMAGE_PORTION * damage);
armor.damage(armorDamage, type);
damage -= armorDamage;
}
}
if (armored == false) {
if (type == Shared.DamageType.BLUNT) {
damage *= Shared.DAMAGE_RESISTANCE;
}
}
super.damage(damage, type);
// Damage effect
EffectManager.addEffect(position);
}


protected void destroy() {
// Remove from entity manager
currentArea.removeCreatureFromCell(this, position);
currentArea.getCreatureManager().removeCreature(this);
// Leave things like debris or a corpse as appropriate
GameFlow.getInstance().getMessageLog().post(
"Creature killed.");
}
So the base damage code is reused via super.damage() within the Creature damage method, and it still calls the correct Creature destroy() method. Thanks again, I would have been really confused had it not been for your assistance earlier.
Logged
Impossible
Level 3
***



View Profile
« Reply #9 on: July 08, 2009, 05:24:26 AM »

Btw, because you seem to be "super" happy, you might want to read this http://en.wikipedia.org/wiki/Call_super.  I don't entirely agree that call super is that bad of an anti-pattern (in certain situations its very useful), but it is often better to refactor your code to avoid it.
Logged
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic