adding multiple inherited objects to a container class - java

I have a program that is well under way, but I can't seem to wrap my ahead around how to add certain classes to a container.
I'm creating a java program for just a 2D person. I have an abstract class, BodyPart (which all body parts share in common), DrawablePart and ContainerPart class implements the abstract class, where Drawable parts include implemented classes such as head, legs, feet, etc; And ContainerParts include implemented classes such as person > upperbody & lowerbody.
The only part I have left to do is create the upperbody and lowerbody classes derived from the container class, which has an array of BodyParts.
Let's say I'm working on LowerBody container, derived from ContainerPart. How is it possible to have a LowerBody constructor that can contain arrays of Legs and Feet (which are derived from DrawablePart)? I would like to have LowerBody and UpperBody derive from Avatar container, which derives from ContainerPart.
I know it's hard getting an answer without showing my code, but I think someone can explain it to me with this UML diagram I created below from my classes.
Here is the UML diagram:
Here is a ContainerPart constructor with an array of BodyParts (super is from BodyPart), which is what I want, but I need certain parts like Leg and Feet in the constructor of LowerBody:
public ContainerPart(String name, String color, int xCoord, int yCoord, BodyPart[] yourParts) {
super(name, color, xCoord, yCoord);
parts = yourParts;
}
In my container class I have an instance field for an array of BodyParts, as seen in the constructor above. But when I try to use more than one derived BodyPart, I get this:
But, if I just have one, say "yourFoot" in super(), it'll work.

I couldn't add this as a comment hence putting here.
If I understand correctly, you have something like below (your real constructor has more arguments):
public abstract class BodyPart {
private String name;
private String color;
......
......
}
public class DrawablePart extends BodyPart {
public DrawablePart(){
super();
}
}
public class ContainerPart extends BodyPart {
public ContainerPart(String name, String color, int xCoord, int yCoord, BodyPart[] yourParts){
super(......);
...........
}
}
public class Legs extends DrawablePart {
public Legs(){
super();
}
}
Now you want to create LowerBody as:
public class LowerBody extends ContainerPart {
public LowerBody(Legs[] legs, Feet[] feet, String name, String color, int xCoord, int yCoord){
super(name, color,xCoord, yCoord, legs);
........
.......
}
public LowerBody(Legs leg, Feet feet, String name, String color, int xCoord, int yCoord){
super(name, color,xCoord, yCoord, new BodyPart[]{leg, feet});
}
}
If yes, what is the problem? It should work fine. If I am missing anything, please let me know.

Maybe a silly question. Why not just have LowerBody extend Avatar? You'd still get the benefits of ContainerPart.
Or you can add a new constructor:
public LowerBody(List<DrawableParts> parts) {
}

Related

How to inherit specific instance variables in java

I want to inherit specific instances from a superclass, not all of them.
For example:
public class Snake extends Reptile {
private boolean hasLegs = false;
public Snake(double[] legLength, double tailLength, String color, boolean hasScales, boolean hasLegs) {
super(legLength, tailLength, color, hasScales);
this.hasLegs = hasLegs;
}
I want to inherit all instance variables from the class Reptile except double[] legLength(as snakes doesn't have legs).
How can I do that without changing code in the Reptile class?
Thanks.
I think you are asking how to not have to pass all the parameters you don't need to the parent class. You can't do that, you need to pass them all, but that doesn't mean you have to expose them all in the child class:
public Snake(double tailLength, String color, boolean hasScales) {
super(null, tailLength, color, hasScales);
this.hasLegs = false;
}
You can't just get some variables from the parent - you get them all. You can set them to values that make sense for your subclass. That is the whole point!

If Downcasting Should Be Avoided, What Should I Do?

have the following interface class:
public interface IGameObject {
String gameObjectID();
String gameObjectName();
void isActionValid(String action);
void viewActions();
}
I have the following abstract class that implements the above interface.
package gameprobjectpackage;
public abstract class Weapon implements IGameObject {
//Left out getters/setters to keep it simple
private String gameOjectID;
private String gameObjectName;
private int damage;
public Weapon(String gameOjectID, String gameObjectName,int damage) {
super();
this.gameOjectID = gameOjectID;
this.gameObjectName = gameObjectName;
this.damage = damage;
}
I've come across a few posts that suggest downcasting should be avoided. I understand why, BUT, my question is what do I do if I need to access a method that is specific to a sub class. For example:
public class ChargeGun extends Weapon {
private String [] chargeGunActions;
public ChargeGun(String gameOjectID, String gameObjectName, int damage) {
super(gameOjectID, gameObjectName, damage);
chargeGunActions = new String [3];
chargeGunActions[0] = "Charge and Fire";
chargeGunActions[1] = "Release";
chargeGunActions[2] = "Drop Gun";
}
//This method is only meant for gun, and this type of gun is the only one in my game.
//This method, I don't belive should be in the abstract method weapon, because NOT every weapon is a gun.
public void reloadGun()
{
}
I store in in an interventory hashmap like so:
Map<String,IGameObject> inventory = new HashMap<String,IGameObject>();
When I retrieve it, I will get an IGameObject, how do I properly cast it, so that I can access the method in ChargeGun?
You can use the visitor pattern which frees you from casting. The idea is simple : You have an inventory of IGameObject which would have a method accept(GameObjectVisitor v) which directly calls v.visit(this). In your GameObjectVisitor, you just have to implement visit methods for each implementations : For example visit(Chargegun g), visit(Sword s), etc...
To explain it another way, it's like the principle of a boomerang : The GameObjectVisitor calls item.accept(this), and the Item implement accept(GameObjectVisitor g) with a simple g.visit(this).
By doing this, the Visitor has multiple visit methods for each implementation and can do specific stuffs without having to cast/using instanceof.

Access methods on different types

I have something like this:
Figures fig = new Line();
on which Line extends Figure. Figure is an abstract class that only has a method getType() that tells me which figure it is by returning a String;
I have 3 types, Rectangle, Circle and Figure. All of them extend Figures.
Now the real question. I store every single one inside of a List<Figures> and I want to get access to some methods on each object like getStartX(); and getStartY(); and I can't, I only can access the methods that are on Figures also.
Your abstract class should define the getStartX and getStartY method. Either abstract if you want Rectangle, Circle and Figure to have a different behaviour and force them to Override those methods. Else just put the method in Figures it'll be available for use (with the appropriate keyword : public/protected depending your needs).
If you want to use methods that are specific to a class you'll need to check of which instance it is. Something like
for (Figures figure: myList) {
int x = figure.getStartX(); // Method common and declared in Figures
if (figure instanceof Circle) {
System.out.println("Oh no a Circle!");
int radius = ((Circle)figure).getRadius();
...
}
}
For your Rectangle/Line you can define an interface with your 2 methods:
public interface HasEndpoints {
int getEndX();
int getEndY();
}
public class Rectangle implements HasEndpoints {
...
public int getEndX() {return endx;}
...
}
for (Figures figure: myList) {
int x = figure.getStartX(); // Method common and declared in Figures
if (figure instanceof HasEndpoints) { // Rectangle and Line will go there
System.out.println("HasEndpoints implementor");
int endX = ((HasEndpoints)figure).getEndX();
...
}
}
You can use instanceof with if...else and cast dynamically your object
Figure fig = new //Circle()/Triangle()/Rectangle();
if( fig instanceof Circle) {
((Circle) fig).getRadius(); //This method is only available in Circle class
}
You can always cast the Figure to Line, but not the best choice. Depending on the problem, you can apply Visitor Pattern or add those methods to Figure, even when the Circle doesn't have a starting and ending point.
For example
public abstract class Figure{
public abstract void visit(FigureVisitor visitor);
}
public class Line extends Figure{
public void visit(FigureVisitor visitor){
visitor.visitLine(this);
}
}
public interface FigureVisitor{
public void visitLine(Line figure);
public void visitCircle(Circle figure);
}
public class StartingPointsVisitor implements FigureVisitor{
private Double startX;
private Double startY;
private Double endX;
private Double endY;
public void visitLine(Line figure){
this.startX = figure.getStartX(); //No cast needed
...
}
public void visitCircle(Circle figure){
//Stub-method
}
//Getters to read the results
}
Is a more complex solution, but as i said, it depends on the problem, and most of the complex remains in the Visitor
Either getStartX() and getStartY() should be declared in Figure class or you need to cast the object to Line class:
Figure figure = figures.get(0);
if ("line".equals(figure.getType())) {
Line line = (Line)figure;
}
Another option is to use reflection. But you still need to be sure, that the requested method can be called.

EnumMap with LuaJava (attempt to call a nil value)

As the title says, I have problem with LuaJava and EnumMap. I'm trying to do a RPG Library, so we have a Character with some Attributes and a list of them. In the code below, I'll report only important things.
I have a class called ConcreteAttribute that extends AbstractAttribute, that has a constructor with a String and two int.
public abstract class AbstractAttribute {
protected String name;
protected int baseValue;
protected double baseMolt;
public AbstractAttribute(String name, int valoreBase, double moltBase){
this.name = name;
this.baseValue = valoreBase;
this.baseMolt = moltBase;
}
/*Getters and Setters*/
}
Then I have an Enum called StatType, that represents the stat you have in RPG games:
public enum StatType {
HP, MP, Attack, Defense;
}
I have also a class called PlayableCharacter, that has (I'll report only important things):
public abstract class PlayableCharacter extends Character{
protected EnumMap<StatType, ConcreteAttribute> statistiche;
//Constructor
public EnumMap<StatType, ConcreteAttribute> getStatistiche(){
return statistiche;
}
and a "put" method from Map.
To create a new character, I'm currently doing this ("Eroe" extends PlayableCharacter):
public static void main(String[] args) {
PlayableCharacter pers = new Eroe("Eroe 1");
ConcreteAttribute atk = new ConcreteAttribute("Attacco", 20, 0);
pers.getStatistiche().put(StatType.Attacco_Fisico, atk);
}
and works fine, but I don't think it is the best solution when you have a lot of ConcreteAttribute and a lot of Character. So I was thinking to use Lua to create "concrete" istance of Character, this way (little example):
-- Eroe 1.lua
function create(eroe)
eroe:setName("Eroe 1")
attributes = luajava.bindClass("personaggi.attributi.StatType")
attacco = luajava.newInstance("personaggi.attributi.ConcreteAttribute", "Attacco", 20, 0)
eroe:getStatistiche():put(attributes.Attacco_Fisico, attacco)
end
but I get this error: PANIC: unprotected error in call to Lua API (attempt to call a nil value). The problem is with the last line, but I'm really new to Lua and I don't even know if Lua can handle EnumMap.
Any solution to this?
Thanks to all and sorry for my bad English ^^
EDIT: I've edited the code, I found an error
An enum constant is public member of its enum class, but you are accessing it like a method using :.
So instead of attributes:Attacco_Fisico you need to use attributes.Attacco_Fisico.

Inheritance, deriving from a derived class

I am trying to create a class from a class that is already derived from another class. (bit confusing) It adds one extra attribute in the newest "PricedApt" class that is "price". The desired constructor call is as follows
PricedApt p = new PricedApt("jill", 900, true, "jack", 1050.00);
The class is missing its constructor and im trying to create it but not sure whats wrong.
This is the (already derived (2nd) class)
public class RentalApt extends Apartment{
private String tenant;
private boolean rented;
public RentalApt(String owner, int size, boolean rented, String who){
super(owner,size);
tenant = who;
this.rented = rented;
}
My code for the (3rd) class that I have attempted is
public class PricedApt extends RentalApt {
private double price;
public PricedApt(String owner, int size, boolean rented, String who, double priceTag) {
super(owner,size,who);
price = priceTag;
}
}
Can anyone point me in the right direction as to what I am doing incorrectly? The compilation error I'm receiving is cannot find symbol (line 2 column 3).
For one, RentalApt has a four-argument constructor, but its subclass PricedApt is calling super() with only three arguments.
Try changing
super(owner,size,who);
to:
super(owner,size,rented,who);

Categories

Resources