Ok, so I have whole module that is in charge of generating player class in my game and after hours and hours of hard labour I came up with this hierarchy (snippets of code without making it too graphic but still providing enough to go on)
I have a base interface for Entities (which are either Player or Monsters):
public interface Entity {
public int getHP();
...
// all getters that denote all stats the Entities have in my game, nothing
else is in the interface
}
Then there is second interface extending Entity, called Classes, that contains all the setters relevant to classes:
public interface Classes extends Entity {
void setHP(int a);
... //and so on}
Finally getting to some real class, class PlayerClasses is responsible for building the classes:
public class PlayerClasses implements Classes {
private int HP, ATK, DEF, DAMAGE, DROP;
#Override
public int getHP() {
return HP;
}
#Override
public void setHP(int a) {
HP = a;
}
// this is how I build the player class
public void Rogue(){
setHP(150);
setATK(30);
setDEF(20);
setDAMAGE();
}
And finally a class which constructor is used to create the player instance that is then passed into other modules (no inheritance or direct access to any other class field or requiring any state in constructor, so win right?)
public class Player {
private int HP,ATK,DEF,DAMAGE,DROP;
private PlayerClasses c;
public Player() {
c = new PlayerClasses();
c.Rogue();
HP = c.getHP();
ATK = c.getATK();
DEF = c.getDEF();
DAMAGE = c.getDAMAGE();
DROP = c.getDrop();
}
Kind of long question, but I tried to keep it civil. Any feedback is very appreciated.
Edit: Ok to clarify why I choose to design like this, I want the player instance to be immutable object that can only be instanced with correct values, while keeping the initialization in other modules as clean as possible without any dependencies. So for example values from two different player classes cannot mix up in case it is instances in module that shows player stats and monster stats. I feel passing private HP and ATK variables in inheritance and then pulluting namespace with same variables is not a way to go for example.
I think I don't understand the reason for an immutable Player class that contains a PlayerClass. But anyways, IMO your Player class is what should inherit the Entity trait. Not the PlayerClasses object that is used as sort of template(?). Because what's the point of having a Player and I assume a similarly constructed Monster class if they aren't both Entity?
You also mix responsibilites / abstractions in an odd way. What is it that is encapsulated in the PlayerClasses and in the Player? PlayerClasses looks like it should represent the class type like "Rogue", not the actual player. And for that it shouldn't have setter methods and neither is a class type an entity.
And a factory like method that initializes a PlayerClasses object is "bad" style. You should always try to guarantee based only on class type that things are right, not have magic methods that need to be called for objects to be right (i.e. no init methods besides the constructor).
Take for example a method that takes a PlayerClasses object as parameter and you want someone else to use that code. They see that they need a reference to PlayerClass and a no-argument constructor for that class, but they can't know what all the initialization steps are. Constructor or various factory / builder patterns can guarantee exactly that.
Here's a draft of how I would have done it:
interface PlayerClass {
int getBaseHp();
int getBaseAtk();
... // more class attributes
}
// as utility so I don't have to write 20 full classes
abstract class PlayerClassBase implements PlayerClass {
private final int hp, atk, ..;
protected PlayerClassBase(int hp, int atk, ...) {
this.hp = hp;
this.atk = atk;
}
#Override
public int getBaseHp() {
return hp;
}
....
}
// short class but guaranteed that every instance of Rogue has the correct values
class Rogue {
public Rogue() {
super(40, 23, 123, ...);
}
}
// something to represent entities
interface Entity {
int getCurrentHp();
int takeDamageFrom(Entity other);
...
}
// maybe an abstract base class here as well
// represents a player that has an immutable class and it can't exist without
class Player implements Entity {
privte final PlayerClass playerClass;
private int currentHp;
...
public Player(PlayerClass playerClass) {
this.playerClass = playerClass;
currentHp = playerClass.getHp();
...
}
public int takeDamageFrom(Entity other) {
currentHp -= other.getCurrentAtk();
return currentHp;
}
}
The PlayerClass part could also be a simple enum instead of a big class hierarchy.
enum PlayerClass {
ROGUE(23, 23, 4, ...),
...
;
private final int hp;
PlayerClass(int hp, int atk, ...) {
this.hp = hp;
...
}
public int getHp() { return hp; }
...
}
That way you could statically reference PlayerClass.ROGUE and create a player like this: new Player(PlayerClass.ROGUE). Instead of currently new Player(new PlayerClass().Rogue()). Or with the big hierarchy: new Player(new Rogue())
Related
I created an Athlete class.
public class Athlete {
private final int id;
private final String name;
private final Country sourceCountry;
public Athlete(int id, String name, Country sourceCountry){
this.id = id;
this.name = name;
this.sourceCountry = sourceCountry;
}
}
then I created the following interfaces and sub classes:
public interface IJumper {
public double jump();
}
public interface IRunner {
public double run();
}
public class Runner extends Athlete implements IRunner {
public Runner(int id, String name, Country sourceCountryCode) {
super(id, name, sourceCountryCode);
}
#Override
public double run() {
return Math.random();
}
}
public class Jumper extends Athlete implements IJumper {
public Jumper(int id, String name, Country sourceCountry) {
super(id, name, sourceCountry);
}
#Override
public double jump() {
return Math.random();
}
}
in addition, I created the following RunnerJumper class to create another type of athlete that can both run and jump:
public class RunnerJumper extends Athlete implements IRunner, IJumper {
public RunnerJumper(int id, String name, Country sourceCountry) {
super(id, name, sourceCountry);
}
#Override
public double jump() {
return Math.random();
}
#Override
public double run() {
return Math.random();
}
}
now, I want to create an Team class. the team should be team of runners or jumpers (team of runners can contain Runner & RunnerJumper and team of Jumpers can contain Jumper & RunnerJumper)
so I want the team to be generic..
in addition the team class should have method like "compete" (
something like: forEach Athlete of Team:
run or jump (depends the type of athlete..)
)
how can I achieve this kind of behaviour?
I tried to create it like this:
public class Team<C extends Athlete> {}
but in this form team of runners cannot contain RunnerJumper..
I also tried to create new interface Competitor:
interface Competitor {}
and have both IRunner & IJumper extend it..
this seems good at first:
public class Team<C extends Competitor> {}
but I don't understand how I can Implement the compete functionality in this form...
It's impossible to do it the way you imagine.
Types - in Java - serve to express guarantees. Things that are 100% certain about a piece of code. If a piece of code gets a Duck, there is 100% guarantee that it is also a Bird and an Animal.
But you cannot express relations like "it's either a Duck or a Bucket". You would need both to extend the same supertype and make sure that the type is only extended by these two; in general it would require multiple inheritance and sealed types.
And you cannot express relations which mix values with types, like "if the numberOfLegs == 8, then the type is Octopus". I have no idea how to call the aparatus required for this, but the structural types in Type Script, I think, can express such constraints. I think that duck typing is a prerequisite.
Coming back to Java: if there's a set of objects which can contain Runners or RunnerJumpers, the only thing that you can guarantee in the Java's type system is that all the objects are Runners. No generics, inheritance etc. can change that.
You can use one of the multitude of patterns to achieve your business goal:
refactor the jumping / running behavior into a separate classes, both implementing Action with a single perform method. Then create an interface with a single method: getActions, called, say, a Player. Then, your Team can iterate over Players, get actions for each one and call their perform method in an inner loop. The implementation of the getAction method can even return a static list of lambdas, so that you can access all your player's attributes from inside. This pattern allows you to keep the list of possible actions open (introducing new actions will not require you to recompile or touch your Team class).
if the list of possible actions is statically known by the Team, you can use the Visitor pattern - let the Team call the player's visit method, and the player can call Team's playerJumps(Jumper j) or playerRuns(Runner r).
Or you can use other mechanisms of the language: reflection and casting (this will also make the list of possible actions static).
What you could do is you could create two Team classes, one for the runners and one for the jumpers, like so:
public interface Team {
public void compete();
}
public class TeamRunners implements Team {
private List<Runner> runners;
private List<RunnerJumper> runnerJumpers;
public Team(List<Runner> runners, List<RunnerJumper> runnerJumpers) {
this.runners = runners;
this.runnerJumpers = runnerJumpers;
}
#Override
public void compete() {
for (Runner runner : runners) {
runner.run();
}
for (RunnerJumper runnerJumper : runnerJumpers) {
runnerJumper.run();
runnerJumper.jump();
}
}
}
public class TeamJumpers implements Team {
private List<Jumper> jumpers;
private List<RunnerJumper> runnerJumpers;
public Team(List<Jumper> jumpers, List<RunnerJumper> runnerJumpers) {
this.jumpers = jumpers;
this.runnerJumpers = runnerJumpers;
}
#Override
public void compete() {
for (Jumper jumper : jumpers) {
jumper.jump();
}
for (RunnerJumper runnerJumper : runnerJumpers) {
runnerJumper.run();
runnerJumper.jump();
}
}
}
I'm learning by solving some exercises and I have to create an Android App using Java, this app has 3 main classes which are Car, Boat and Tow. These 3 classes share some attributes , for example, Car and Tow both have a Licence Plate and both Car and Boat have a load weight. Right now what I'm doing is creating two abstract classes, Vehicle and VehicleWithPlate, where Car inherits from VehicleWithPlate and Boat inherits from Vehicle. VehicleWithPlate inherits from Vehicle.
This might not even be the best approach, but the thing now is that I need to implement the load weight into one of these superclasses, and create a VehicleWithWeight is not the best option, since if a vehicle has both weight and a plate, there would be a conflict. I know a way to "implement" multiple inheritance in Java is using interfaces, and I know interfaces just implement abstract methods, not attributes . What would be the best approach to do this? My solution so far has been to implement the loadWeight property into Vehicle and Boat individually, but that doesn't look as clean.
Car
public class Car extends VehicleWithPlate{
private float loadWeight;
public Car(String plate, int passengersNum, int maxPassengers, float loadWeight) {
super(plate, passengersNum, maxPassengers);
this.loadWeight= loadWeight;
}
public float getLoadWeight() {
return loadWeight;
}
}
Boat
public class Boat extends Vehicle{
private float loadWeight;
public Barco(int passengersNum, int maxPassengers, float loadWeight) {
super(passengersNum, maxPassengers);
this.loadWeight= loadWeight;
}
public float getLoadWeight() {
return loadWeight;
}
}
Vehicle
public abstract class Vehicle {
protected int passengersNum;
protected int maxPassengers;
public Veiculo(int passengersNum, int maxPassengers){
this.passengersNum= passengersNum;
this.maxPassengers= maxPassengers;
}
}
VehicleWithPlate
public abstract class VehicleWithPlate extends Vehicle {
protected String plate;
public VehicleWithPlate (String plate, int passengersNum, int maxPassengers) {
super(passengersNum, maxPassengers);
this.plate= plate;
}
public String getPlate() {
return plate;
}
}
Maybe there's something I'm missing, and I know that repeating some code is not the end of the world, but I'm really curious as a student for a professional approach to something this basic.
Take a look at the difference between design by composition and design by inheritance: here. Sounds a lot like you really have a few classes here. A LicensePlate class, a LoadWeight class, and all of your vehicle classes that you mentioned before. The two new classes are all “has-a” type relationships, as opposed to "is-a" type relationships (A Car has-a LicensePlate, a Boat has-a LoadWeight). Hope this helps!
Alternatively, you can just extract the weight property to an interface:
public interface Weighted {
float getLoadWeight()
}
That way, you can upcast to "Weighted" when required, but will still have to implement the property individually
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I am having trouble deciding between these three ways to handle field variables for a subclass and superclass.
Method 1:
public abstract class Vehicle {
public abstract int getNumberOfWheels();
public abstract int getCost();
}
public class Car extends Vehicle {
private int numberOfWheels;
private int cost;
public Car() {
this.numberOfWheels = 4;
this.cost = 10000;
}
public int getNumberOfWheels() {
return numberOfWheels;
}
public int getCost() {
return cost;
}
}
With this method i have to implement the same duplicate getter methods in every subclass of Vehicle. I imagine this would be a problem with more complicated getter method, that have to be duplicated and eventually maintained.
Method 2:
public abstract class Vehicle {
private int numberOfWheels;
private int cost;
public int getNumberOfWheels() {
return numberOfWheels;
}
public int getCost() {
return cost;
}
public void setNumberOfWheels(int numberOfWheels) {
this.numberOfWheels = numberOfWheels;
}
public void setCost(int cost) {
this.cost = cost;
}
}
public class Car extends Vehicle {
private int numberOfWheels;
private int cost;
public Car() {
super.setNumberOfWheels(4);
super.setCost(10000);
}
}
With this method i have to implement setter methods that i might not want to have. I might not want other classes to be able to change the fields, even in the same package.
Method 3:
public abstract class Vehicle {
private int numberOfWheels;
private int cost;
public class Vehicle(int numberOfWheels, int cost) {
this.numberOfWheels = numberOfWheels;
this.cost = cost;
}
public int getNumberOfWheels() {
return numberOfWheels;
}
public int getCost() {
return cost;
}
}
public class Car extends Vehicle {
private int numberOfWheels;
private int cost;
public Car() {
super(4, 10000);
}
}
With this method and with a lot of fields, the amount of constructor parameters will grow huge, which just feels wrong.
It seems like this would be a common enough problem for there to exist some kind of "best practice". Is there a best way to do this?
Several thoughts here:
It is actually good that you don't get into the protected fields story; one should avoid sharing fields between base/extending classes if possible.
Similarly, it is also good practice to avoid using setters. That kinda rules out your second options.
Further on ...
You could rewrite your subclass in option 1 to:
#Override // always use that when OVERRIDING methods!
public int getNumberOfWheels() { return 4; }
In your option 1, those numbers are actually constants as your code is not showing any means to change those values. So there is no need to use fields in the derived classes! Unless of course, you might imagine different types of Cars, and a need to allow for 3 or 5 wheels as well. In that case, you would offer a default ctor; and one that takes that number-of-wheels (to then store it in some final property).
Then: you are correct, when a lot of information would be required, that option3 using constructors will "blow up" on you. But: that would be just a consequence of a design problem anyway. Because: one should be conservative about number of fields anyway. Meaning: if your class carries so many fields that init'ing them via constructors looks like a problem, than that is an indication that you got too many fields in the first place! In such a situation, you would look into your model to figure which properties really belong into your class.
Example: in your code, you are representing "cost" as property of your base class. But is that really true? Is its "prize" really an essential property of any vehicle? What I mean is: a car is just a car; it doesn't "care" about its value. That value is some extrinsic property, that other systems would impose on that car. Meaning: a vehicle doesn't necessarily need a price/cost property. You only start thinking about that when vehicles are entities in some bigger context that deals with the values of its entities. So some other EntityManager thingy might be a better place to keep track of vehicles and their corresponding (current) value.
Good practice is rather relative here; in your case, it depends on what you are trying to achieve.
Will any subclass of Vehicle have a number of wheels and a cost associated? If the answer is Yes, then it is good practice to add them to the superclass. If you may have TrackVehicle as subclass, then numberOfWheels is not applicable here and hence does not belong in the superclass.
Ask yourself the question: do you really need setters? Will you have to change the state of your instance after creation? If not, don't add them: you can create a constructor in the superclass that takes the total number of required parameters and use it in every subclass:
public Car(int numberOfWheels, int cost) {
super(numberOfWheels, cost);
}
By trying to guess your intention, this would be my method of doing it:
public abstract class Vehicle {
private int numberOfWheels;
private int cost;
public Vehicle(int numberOfWheels, int cost) {
this.numberOfWheels = numberOfWheels;
this.cost = cost;
}
public int getNumberOfWheels() {
return numberOfWheels;
}
public int getCost(){
return cost;
}
}
and a specific subclass where every Car has 4 wheels and a cost for the outside world that is actually much bigger than the initial one (just to show the fact that you can override a method if required, no need to duplicate it)
public class Car extends Vehicle {
public Car(int cost) {
super(4, cost);
}
#Override
public int getCost(){
return cost * 2;
}
}
About the 'constructor parameters will grow huge' problem: have a look at the 'Builder' design patters. (Effective Java - Builder pattern)
I am having trouble deciding between these three ways to handle field variables for a subclass and superclass.
In the first place you should prefer composition over inheritance which means that concrete classes do not inherit from each other, only interfaces.
Beside this your question somehow depends on the purpose of your classes.
Classes can either be "plain value classes" without any business logic (aka data transfer objects - DTOs) or "regular" objects.
DTOs
When you're desining DTOs you should create them as beans which means that you should create public getter methods for each property. By any chance you should make your DTOs immutable which means all member variables are declared with the final keyword. Then you have to set the values via constructor.
However: some frameworks require DTOs with default constructors and setters for the member variables.
regular objects
In all other classes you should not provide access to member variables of a class neither directly nor via getters/setters. This would violate the most important OO principle: information hiding aka encapsulation.
Initial values should be set via constructor and when you have the need to modify a member value you should provide methods with business related names.
eg.:
class Vehicle {
private int speedInMph;
private final int maximumSpeedInMph;
public Vehicle(int initialSpeedInMph, int maximumSpeedInMph){
this.speedInMph=initialSpeedInMph;
this.maximumSpeedInMph=maximumSpeedInMph;
}
public void accelerateBy(int accelerationInMph){
this.speedInMph+=accelerationInMph;
if(maximumSpeedInMph<this.speedInMph)
this.speedInMph=maximumSpeedInMph;
}
public void decelerateBy(int decelerationInMph){
this.speedInMph-=decelerationInMph;
if(0>this.speedInMph)
this.speedInMph=0;
}
}
Imagine that I have some classes that looks like this:
class Car {
private Image carImage;
public Car(int imageIndex) {
switch (imageIndex) {
case 1: carImage = generateCarImage(1); break;
# and so forth
}
}
}
class Audi extends Car {
private int numberOfSeats;
public Audi(int imageIndex, int numberOfSeats) {
super(imageIndex);
this.numberOfSeats = numberOfSeats;
}
}
Now imagine that I create multiple Audi's using the same image:
Audi car1 = new Audi(1,2);
Audi car2 = new Audi(1,3);
Will car1 and car2 extend the same object? I assume not, but is there a way I can make it so? I'm asking because I want to avoid generating and storing the same image twice.
EDIT:
Will these two audi's reference the same car, e.g. the image is generated and stored only once, and any changes to one affects the other?
class Car {
private Image carImage;
public Car(int imageIndex) {
switch (imageIndex) {
case 1: # carImage = readfile(1.jpeg)
# and so forth
}
}
}
class Audi{
private int numberOfSeats;
private Car car;
public Audi(Car car, int numberOfSeats) {
this.car = car;
this.numberOfSeats = numberOfSeats;
}
}
Car car = new Car(1);
Audi audi1 = new Audi(car,2);
Audi audi2 = new Audi(car,2);
EDIT 2:
There are a lot of good answers here, and I ended up using a combination of them to create a decent solution. My initial problem was not very well defined, mainly because I didn't know myself exactly what it was.
Anyway, for this problem it is not possible to generate all the data (PartsInfo in the example below) beforehand, nor can I generate the data explicitly (as implied by the switch-case example above). The biggest problem with the solution below is that I can't access individual fields in PartsInfo without retrieving the whole thing (as is done in the solution when Car.getPartsInfo() is called) or creating multiple instances of the same object (in which case the Car class would get its own PartsInfo variable).
A weak hashmap would also do, but not optimal because the problem is not garbage collection, but huge amount of identical data stored in separate instances.
The solution is applicable if the ID is something like "audi-a4-2003" and PartsInfo is identical for all "audi-a4-2003" independent of color, owner, age, number of seats etc, but completely different for "audi-a4-2004".
Thanks
Class PartsInfo {
// lots of stuff I'd rather not create nor save multiple times
}
Class PartsInfoFactory {
private static HashMap<String, PartsInfo> partsInfoMap = new HashMap<String, PartsInfo>();
public static getPartsInfo(String id) {
if (!partsInfoMap.containsKey(id)) {
generatePartsInfo(id);
}
return partsInfoMap(id)
}
private static generatePartsInfo(String id) {
// Do stuff I don't want to do twice for same ID
partsInfoMap.put(id)
}
}
Class Car {
private Color color;
private String id;
// Notice that PartsInfo is not stored here
public Car(Color color, String id) {
this.color = color;
this.id = id;
}
public PartsInfo getPartsInfo() {
return PartsInfoFactory.getPartsInfo(id);
}
}
Will car1 and car2 extend the same object?
A class can extend from another class.. Objects do not extend anything. In Java, inheritance is just for classes and interfaces. What you're doing here is creating two instances of the same class, Audi, and Audi extends from Car.
is there a way I can make it so?
No.
I'm asking because I want to avoid generating and storing the same image twice.
This is the proper question to answer. Your real problem is dealing with avoiding to create the same object instance multiple times. For this, it will be better to use an object pool by making use of a WeakHashMap. Here's an explanation on why to use this structure: When would you use a WeakHashMap or a WeakReference?
A good way to avoid creating the same image multiple times is to use dependency injection: inject the image as a constructor parameter, rather than passing in the parameter to generateCarImage:
class Car {
private final Image image;
Car(Image image) {
this.image = image;
}
}
class Audi extends Car {
Audi(Image image, int numDoors) {
super(image);
// ...
}
}
This means that image can come from anywhere - giving you more explicit control over the lifecycle of the images. So, if you want to use the same image over and over, you can, and it's obvious that you are:
Image image = generateCarImage(1);
Audi car1 = new Audi(image, 4);
Audi car2 = new Audi(image, 2);
Also, by removing static coupling to your generateCarImage method, it makes the class more testable, since you can create different images for testing, e.g. that are simpler to generate.
You never extend objects, you extend the class. And of course you will be extending the same class all the time.
Everytime you're using the new clause you will be creating a new instance of the object, a complete separate representation of the class; so answering to the direct question: no, you're not extending the object.
The underlying question is that you may not want to repeat the creation of to equal images: Then you must make a different approach. I recomend first to do another read to the OO aspect of Java, then think on (maybe) the factory patter which could be a class that will take care of not repeating the creation of to equal images if another was already created.
In Java there is no such thing as extending an object (other languages have this kind of inheritance, called prototypal. However, Java does not have prototypal inheritance; only a class inheritance).
Extending in Java means extending a class, not an object, which is an instance of a class.
Therefore, although the classes of car1 and car2 extend the same class, the two objects are unrelated to each other.
I want to avoid generating and storing the same image twice
There is no problem with multiple objects sharing a third object, which in your case could be an image. One way to deal with this would be creating an image cache common to all instances of Car, generate the image the first time that it is requested, and then re-using the same image object as needed to save space:
Is it possible to, instead of searching a cache of images, searching through a cache of all instances of Car, and then choose which one to instantiate in the Audi class?
You cannot instantiate an object for a second time. However, you can make a cache of Car objects, and implement a factory method on the Car that searches its cache for a suitable car before making a new instance.
My solution is using static references to be used as constant values. This is the easiest solution, given that enum won't work with objects, since it has to be evaluated at compile-time.
But we want to get both a run-time constants, and the benefit of using an enum like using single-instance and can be used in a switch statement.
So we are going to implement the enum to return constant static attributes of another class which is available at compile-time, and return a constant reference to an object created on run-time.
class CarImageDirectory
{
// Created at Run-time
public static final Image Audi = new Image("Audi");
public static final Image Toyota = new Image("Toyota");
// ..etc
}
enum CarImage
{
// Created at Compile-time
Audi
{
#Override public Image image () { return CarImageDirectory.Audi; }
},
Toyota
{
#Override public Image image () { return CarImageDirectory.Toyota; }
}; // ..etc
public abstract Image image ();
}
CarImage will work like this:
CarImage A = CarImage.Audi;
CarImage B = CarImage.Audi;
if (A == B) System.out.println("A and B are both Audi");
Then we just define our Car class using it:
class Car
{
private CarImage carImg;
public Car (CarImage carImg) { this.carImg = carImg; }
public Image getImage () { return carImg.image(); }
public CarImage getCarImage () { return carImg; }
}
class AudiCar extends Car
{
private int numOfSeats;
public AudiCar (int numOfSeats)
{
super(CarImage.Audi);
this.numOfSeats = numOfSeats;
}
}
class ToyotaCar extends Car
{
private int numOfSeats;
public ToyotaCar (int numOfSeats)
{
super(CarImage.Toyota);
this.numOfSeats = numOfSeats;
}
}
Also CarImage itself can be used in switch statement too:
CarImage A = CarImage.Audi;
switch(A)
{
case CarImage.Audi:
System.out.println("This car is Audi");
break;
case CarImage.Toyota:
System.out.println("This car is Toyota");
break;
default:
}
Have you looked into "flyweight" pattern? That might reduce object creation for you.
Technically, it's for reducing memory footprint, but if object creation is expensive and there is high reuse, you can use it in situations where startup time is not an issue, such as with application-server startups.
In any event only optimize if you know it's a performance problem.
Hope this helps!
I've been working on a little inventory system just to practice my OO programming. I am using Java 7 in Netbeans.
The player will have an inventory (ArrayList of base Item Class), all items created will be a child of that base Item class.
No items should be of type BaseItem, they will all extend off of that, so to my understanding, the BaseItem class should be abstract?
public abstract class BaseItem {
protected GoldValue itemValue;
protected String itemName;
//accessors and mutators down here
}
Child item types will also have different properties, which I was going to implement as Interfaces, such as Stackable, Consumable, etc.
The interface looks something like this
public interface Stackable {
public void stack (StackableItem bi1);
}
As you can see, I make a reference to StackableItem here, that is one of the children of BaseItem, which is also abstract and specific items will build out of.
public abstract class StackableItem extends BaseItem implements Stackable{
protected int quantity;
protected int maxStacks;
#Override
public void stack (StackableItem si)
{
if(this.getQuantity() + si.getQuantity() < maxStacks){
this.setQuantity(this.getQuantity()+si.getQuantity());
si.setQuantity(0);
}
else if(this.getQuantity() + si.getQuantity() > maxStacks){
int diff = maxStacks - this.getQuantity();
this.setQuantity(this.getQuantity() + diff);
si.setQuantity(si.getQuantity() - diff);
}
}
}
and here's an example of a specific item:
public class StackableItemExample extends StackableItem{
public StackableItemExample ()throws GoldException
{
this(new GoldValue(0,0,0), "unnamed", 1);
}
public StackableItemExample(GoldValue gv, String name, int quan) throws GoldException
{
this.itemValue = gv;
this.itemName = name;
this.quantity = quan;
this.maxStacks = 10;
this.itemValue.setGoldValue(gv.getGold()*quan, gv.getSilver()*quan, gv.getCopper()*quan);
}
}
My Inventory, being an ArrayList of BaseItem objects, is allowed to have a StackableItemExample object inserted into it no problem. The issue is, my inventory system cannot say BaseItem.stack() since the parent has no knowledge of this method.
I want to make a very easily extendable item system, that a new item can be created with extreme simplicity by implementing and extending pre-created classes and interfaces, but this is getting in my way.
No items should be of type BaseItem, they will all extend off of that, so to my understanding, the BaseItem class should be abstract?
Sounds good to me
If you want BaseItem.stack() to work, you could do at least two things:
Move stack() into your base class, and give it a default implementation of doing nothing. Then override that in your StackableItem class, or
Use instanceof to see whether the BaseItem is a StackableItem, then cast it to a StackableItem and go from there.
The second approach would look like:
BaseItem item = YourList.get(i);
if(item instanceof StackableItem){
StackableItem stackable = (StackableItem)item;
stackable.stack() /* Now works without issue */
}
Make every item Stackable - currently unstackable items should have a stack size of one. You could then get rid of the stackable abstract class and interface, putting that functionality into the base class.