I created some classes with inheritance concept, I have the main class for my application, that is called modulo, which corresponds to an module, and also some other classes called moduloLedRGB, ModuloSwitch, and ModuloDimmer, these 3 classes all extends the class modulo which has just the common arguments for modules like, id, name, Module type, and ipAdress. But, when I try to cast a module to one of those 3 childs classes I get an exception that says I cannot cast Modulo to ModuloSitch or ModuloLedRGB...
This is where I get the error:
switch (modulo.getModulo()){
case "RGB":
ModuloLedRGB rgb = (ModuloLedRGB) modulo;
rgb.setProgress(c.getDouble(c.getColumnIndex("progress")));
rgb.setProgressRed(c.getDouble(c.getColumnIndex("progressRed")));
rgb.setProgressGreen(c.getDouble(c.getColumnIndex("progressGreen")));
rgb.setProgressBlue(c.getDouble(c.getColumnIndex("progressBlue")));
break;
case "Dimmer":
ModuloDimmer dimmer = (ModuloDimmer) modulo;
dimmer.setProgress(c.getDouble(c.getColumnIndex("progress")));
break;
case"Switch":
ModuloSwitch sw = (ModuloSwitch) modulo;
break;
It says I cannot cast modulo that is an object corresponds to the class Modulo, to ModuloRGB.
getModulo returns a string that says me which kind of Module this is.
package br.com.andrey.projetointegradoapp;
/**
* Created by andrey on 04/08/2016.
*/
public class Modulo {
private long id;
private String nome;
private String ModuleIpAdress;
private String modulo;
public String getModulo() {
return modulo;
}
public void setModulo(String modulo) {
this.modulo = modulo;
}
public String getModuleIpAdress() {
return ModuleIpAdress;
}
public void setModuleIpAdress(String moduleIpAdress) {
ModuleIpAdress = moduleIpAdress;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
}
This is the Modulo Class.
and this is ModuloLedRGB class:
package br.com.andrey.projetointegradoapp;
/**
* Created by andrey on 16/12/2016.
*/
public class ModuloLedRGB extends Modulo {
private double progress;
private double progressRed;
private double progressGreen;
private double progressBlue;
public double getProgressRed() {
return progressRed;
}
public void setProgressRed(double progressRed) {
this.progressRed = progressRed;
}
public double getProgress() {
return progress;
}
public void setProgress(double progress) {
this.progress = progress;
}
public double getProgressGreen() {
return progressGreen;
}
public void setProgressGreen(double progressGreen) {
this.progressGreen = progressGreen;
}
public double getProgressBlue() {
return progressBlue;
}
public void setProgressBlue(double progressBlue) {
this.progressBlue = progressBlue;
}
}
Any ideas for why am I getting this exception? since the child extends the main class I think I should be able to cast it down, not?
Based on the comments, it appears that you misunderstand the nature of casting.
When you say
class Modulo { ... }
class ModuloLedRGB extends Modulo { ... }
Subclassing defines an is-a relationship; every ModuloLedRGB is also a Modulo. But that doesn't work both ways.
If you create an object with
new Modulo()
then it is a Modulo, but not a ModuloLedRGB. If you create it with
new ModuloLedRGB()
it is both a ModuloLedRGB and a Modulo. Saying it's a Modulo means that you can assign a variable of type Modulo to it, or use it as a Modulo parameter:
ModuloLedRGB x = new ModuloLedRGB();
Modulo y = x; // this is legal, but the object's class doesn't change
y is a reference to the ModuloLedRGB object. But note that although y is declared as Modulo, it still refers to the same object, whose class is ModuloLedRGB, because that's the way the object is created.
That's why you can use downcasting. Say you later use the expression
(ModuloLedRGB)y
At this point, the compiler knows only that y (if not null) is a Modulo; it could be an object of class Modulo, ModuloLedRGB, ModuloSwitch, or anything else. So at run time, the code checks to see what kind of object it's actually referring to. Since the example above set y to an object created as a ModuloLedRGB, the cast is successful. But if y were set to some other object that wasn't a ModuloLedRGB, the cast throws an exception.
This cast doesn't change an object, and it doesn't create a new object. It just says "Make sure the object is of class ModuloLedRGB, and then treat it as a ModuloLedRGB so that we can access methods and instance variables that are particular to a ModuloLedRGB".
It looks, however, that you're trying to convert the object by changing its class. You've created an object whose class is Modulo, and you're trying to come up with some new object whose class is ModuloLedRGB. You can't do that with a cast. If you have a Modulo and you want to create a ModuloLedRGB, you will have to create a new object with new ModuloLedRGB(), somewhere. One common way to do this is to write a constructor:
class ModuloLedRGB extends Modulo {
public ModuloLedRGB(Modulo m, maybe other parameters) {
// copy the instance variables from "m"
this.field = m.field;
this.anotherField = m.anotherField;
// set the new instance variables
this.newField = maybe a parameter or some other computation;
...
}
or write a static factory method to create a new ModuloLedRGB from a Modulo. But you'll have to create it, and you'll have to write the code to create it. You can't "convert" it from a Modulo. There's no such thing in Java.
Related
I am confused as to the definitions and the logistics behind the superclass and subclass.
In a word - yes. Since a subclass instance "isA" superclass, you can assign it to such a variable.
Consider the following example - a String is an Object, so this assignment would be legal:
Object obj = "abcd"; // this is a string literal
To quickly answer your question: yes, it is possible to assign a subclass almost anywhere the superclass goes.
The reasons for this involve inheritance and object oriented programming. Let me give you an example. Let's think about trains and railway cars that are part of the train.
The superclass is RailwayCar. Every RailwayCar has a weight.
public class RailwayCar {
private int weight;
public RailwayCar() {
}
public RailwayCar(int weight) {
setWeight(weight);
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public void arriveAtStation(Station station) {}
public void leaveStation(Station station) {}
}
That is just a basic car. However, there are special cars.
// Engines have power in addition to weight
public class Engine extends RailwayCar {
private int power;
public Engine(int weight, int power) {
super(weight);
setPower(power);
}
public void setPower(int power) {
this.power = power;
}
public int getPower() {
return power;
}
}
There are other types of cars. For example, for example, there could be a PassengerCar where the weight might change at each station as passengers get on and off. There are specific types of cars for specific types of cargo. LogCar would contain long logs.
All of these subclasses of RailwayCar may override the station methods (arriveAtStation() and leaveStation()) to perform specific actions by overriding these methods.
All of these cars could be put into the same list or array. For example, RailwayCar[] cars, or List cars = new ArrayList<>();
Whenever I try to get a field from an enum, it always returns null.
I've set the value of it according to the enum constructor. It still comes out null.
public enum TeamType {
RED("Red",ChatColor.RED,DyeColor.RED,Point.RED),
BLUE("Blue",ChatColor.BLUE,DyeColor.BLUE,Point.BLUE); //<----Set as Point.RED/BLUE
private String name;
private int crystalHealth = 50;
private Point point;
private int teamPoints;
private ChatColor chatColor;
private DyeColor dye;
private HashSet<ArenaPlayer> playerList = new HashSet<>();
private List<ArenaPlayer> queue = new ArrayList<ArenaPlayer>();
private Location spawn;
public Point getPoint()
{
if(point == null)
System.out.println("WHY? for: " + this.toString()); //<---This always runs
return point;
}
private TeamType(String name,ChatColor color,DyeColor dye,Point point1) {
this.name = name;
this.point = point1; // <--- My assignment
this.dye = dye;
this.chatColor = color;
}
The Point enum class
public enum Point{
RED(ChatColor.RED + "Red",TeamType.RED),
BLUE(ChatColor.BLUE + "Blue",TeamType.BLUE),
NEUTRAL(ChatColor.WHITE +"None",null);
private String name;
private TeamType teamOwned;
private Point(String name,TeamType team) {
this.name = name;
teamOwned = team;
}
public TeamType getTeamOwned() {
return teamOwned;
}
public String getName() {
return name;
}
#Override
public String toString() {
return name;
}
There's obviously something that's happening outside of my knowledge of Java.
Could it possibly be that the Point Enum is not initialized yet when TeamType enum is. This could explain why it's null.
I need some help.
Well, I think the source of the problem is that you have a circular reference. TeamType has a Point reference and vice versa.
Suppose the TeamType enum class is initialized, then the enum constants are initialized as well. These refer to Point, which is in turn initialized. The classloader loads the Point class, but will not initialize TeamType again. At this point, properties you expect to be non-null are still null.
The JLS § 12.4 defines this process.
Suppose we have a class called A which has class B’s Object. (in UML terms A HAS B). at the same time we class B is also composed of Object of class A (in UML terms B HAS A). obviously this represents circular dependency because while creating the object of A, the compiler must know the size of B... on the other hand while creating object of B, the compiler must know the size of A. this is something like egg vs. chicken problem...
to avoid such type of circular dependency you can use any proxy interface .
https://dzone.com/articles/tackling-circular-dependency
I'm working on a java based game with a friend and I've noticed he's taking an approach that concerns me, in terms of maintainability.
For a class representing a playable Character, instead of just creating 1 method which sets an object's property, he's creating separate methods which set the property to a specific value.
Which of these 2 options would be the best to follow going forward?
Option 1
public void runFast() {
this.character.speed = 5.0f
}
public void walk() {
this.character.speed = 2.0f
}
public void stop() {
this.character.speed = 0.0f;
}
Option 2
public void setSpeed(float speedTemp) {
this.character.speed = speedTemp;
}
Why not use an enum to set the speed - then you can still have
void setSpeed(Speed speed) {
this.character.speed = speed.getAmount();
}
with:
enum Speed {
FAST(5.0f), WALK(2.0f), STOP(0.0f);
private final float amount;
private Speed(flaot a) { this.amount = a; }
public float getAmount() {
return amount;
}
}
That way, you can quickly update the values, but still have a predefined amount. Its flexible and easy to maintain. You might want to save the enum instead of the float.
My Solution would be to use Enums instead,
it is cleaner and has more context and easily extensible if you have more to do with your speed maxHeartRate in the future.
public class Character {
private Speed speed;
public Speed getSpeed() {
return speed;
}
public void setSpeed(Speed speed) {
this.speed = speed;
}
};
public enum Speed {
STOP(0),
RUN(5.5),
WALK(2.5);
double value;
Speed(double value) {
this.value = value;
}
public double getValue() {
return value;
}
};
IMHO the best option would be to declare constants/enums, and use the option 2.
Example (constants) :
public static final float STOP = 0.0f;
public static final float WALK = 2.0f;
public static final float FAST = 5.0f;
setSpeed(STOP|WALK|FAST);
Example (enums) :
public enum Speed
{
FAST(5.5f),
STOP(0),
WALK(2.5f);
float value;
Speed(float pValue)
{
this.value = pValue;
}
public float getValue()
{
return this.value;
}
}
setSpeed(Speed.FAST);
It depends. For example
Are speeds limited to a few predefined values? In that case using an enum would be a good solution.
Is walking / running / stopping going have side effects other than just setting the speed? As a contrived example, starting to run might cause the character to drop an item it's holding, or stopping might cause the character to skid a little. In this case having separate methods might make sense.
Or maybe there are only a few predefined states, but depending on the environment running speed might be different.
What it comes down to is: Which way of conceptually modeling the properties of your character works best for your game logic / physics? Work this out and then base the interface of your classes on that. Don't get too hung up on the exact API early on, this sort of stuff is pretty easy to refactor.
getter and setters are useful when you want that your code is readble and for avoiding that public class fields can be used in the wrong way from another classes.
This example show how is important.
CLASS A:
public class ClassA{
// in the body class
private String fieldClass1;
//classic setter
public void setfieldClass1(String f1)
{
fieldClass1 = f1;
}
}
CLASS B:
public class ClassB{
// in the bodyclass
public String fieldClass2;
//classic setter
public void setfieldClass2(String f2)
{
setfieldClass2 = f2;
}
CLASS C:
public class ClassC{
//in the body of the class this method use class a and class b
public void calc()
{
ClassA aObject = new ClassA();
ClassB bObject = new ClassB();
ClassA.fieldClass1 = 5 + 5; // illegal expression for the compiler and costrain the developer to use setters
ClassB.fieldClass2 = 8 + 8; // legal expression
}
}
This mean that you must define a "modifiers logic" (protected, private, public) before make setters and getters. Define before the modifiers and after define the setters and getters.
I'd like to write an exception class which is usable with different classes and specific behaviors. It works well with changing an object - like
a.setWeight(500)
- but it doesn't work in my constructor - like
Cheese b = new Cheese(500);
because the object is not being generated and null is inserted in my WeightException.
public class WeightException extends Exception {
private int attribute;
private Object object;
public WeightException(Object o, int a) throws WeightException {
object = o;
attribute = a;
}
public String getMessage() {
if(object instanceof Cheese)
return "Cheese is overweight.";
if(object instanceof Baggage)
return "Baggage is "+String.valueOf(attribute)+" kilos overweight.";
}
}
public class Cheese {
private int weight;
public Cheese(int weight) {
setWeight(weight);
}
public void setWeight(int weight) throws WeightException {
if(weight<200)
this.weight = weight;
else
throw new WeightException(this, weight);
}
}
Does anybody know a better approach to solve this than to insert a string with the class name in my exception class parameters?
Implement an interface in the classes you want to use with this exception.
The interface has a method to define a message, possible another to provide an attribute.
Alternatively, provide an array of attributes and use String.format to build the message.
Use that interface to define the object parameter passed in to the exception ctor.
Call that method in the exception to get the message.
Personally, I find this to be an anti-pattern, unless the classes you want to use with the exception are very tightly related. Otherwise you're giving up semantically-meaningful exception property names.
I'd rather see an app-specific superclass with subclasses with semantic meaning.
Here is a solution which would require that you use a "toy" project of mine (well, I already use it in other projects):
Make a base abstract class like this:
public abstract class WeightedItem
{
protected static final MessageBundle BUNDLE;
static {
// The day when you get serious, replace with a properties bundle
final MessageSource source = MapMessageSource.newBuilder()
.put(Cheese.class.getCanonicalName(), "cheese is overweight")
.put(Baggage.class.getCanonicalName(), "baggage is %d kilos overweight")
.build();
BUNDLE = MessageBundle.newBuilder().appendSource(source).freeze();
}
protected int weight;
protected final WeightException doException(final Object... params)
{
return new WeightException(BUNDLE.printf(getClass().getCanonicalName(),
params));
}
}
An implementation of Baggage would then do:
public class Baggage
extends WeightedItem
{
// ....
public void setWeight(int weight)
throws WeightException
{
if (overweight)
throw doException(weight);
}
}
As the implementation is both key-resistant (returns the key if missing) and format-resistant (returns the format string itself if format argument mismatch) you are guaranteed to have parameterized messages or quickly see where you got your messages wrong...
Have you actually tried running this code? The this variable is valid (non-null) within a constructor. Even if the constructor throws an exception, a new object has been created and can be referenced. See the JLS.
If you parameterize the exception with everything you need for the message, you can rid yourself of using instanceof, and make the exception usable by any class:
Also, it's not a good idea to hold a reference to the object that caused the exception - it's unnecessary, is a form of memory leak, but importantly if the exception is thrown from the constructor, will allow this to "escape" from the constructor (always bad).
public class WeightException extends Exception {
private final int attribute;
private final String className;
private final String units;
public WeightException(Object o, int a) {
this(o, a, null);
}
public WeightException(Object o, int a, String u) {
classname = o.getClass().getSimpleName(); // eg "Cheese"
attribute = a;
units = u == null ? "" : u + " ";
}
public String getMessage() {
return className " is " + attribute + " " + units + "overweight.";
}
}
You can now use this exception with any class without further modification of the exception or the client class, other than to provide the optional units:
From Cheese:
throw new WeightException(this, weight);
From Baggage:
throw new WeightException(this, weight, "kilos");
I have one supertype defined as:
public abstract class AType<T> {
....
private T value;
private T mask;
public T getValue() {
if (isMasking())
return null;
return this.value;
}
public void setValue(T value) {
if (value == null)
throw new IllegalArgumentException("Value is mandatory.");
this.value = value;
}
protected T getMask() {
if (!isMasking())
return null;
return this.mask;
}
protected void setMask(T mask) {
if (mask == null)
throw new IllegalArgumentException("Mask is mandatory.");
this.setMasking(true);
this.mask = mask;
}
...
}
and few subtypes like:
public class SpecType extends AType<Integer> {
...
}
these sub types specifies the unknown parameter.... i have more f.e. IPv4, Long, and so on
now i need to somehow in runtime do a dynamic cast...
i have these classes defined in enum like this:
public enum Type {
SOME_TYPE(new TypeID(0, (short) 0), OFMU16.class,
new Instantiable<AType<?>>() {
#Override
public SpecType instantiate() {
return new SpecType(new OFMatchTypeIdentifier(0, (short) 0));
}
}),...;
...
public Class<? extends AType<?>> toClass() {
return this.clazz;
}
...
}
I want do something like:
AType<?> type = SOME_TYPE.newInstance(); //this works
SOME_TYPE.toClass().cast(type).setValue(10); //this don't work
so I have to do it statically:
((SpecType) type).setValue(10);
Everything would be OK, but the user of this module will not want to look in enum and cast manually every time. This will probably make mistakes and spend a lot of time with debugging :/....
My question is how can I refactor this or how do I define structure of inheritance to allow user to cast dynamically? Is it possible?
Edit:
I am parsing packets from network. There is a lot types which differs in Vendor Type identifier and type of Value/Mask - these fields are all constant for every this combination, so i has defined it as enum constants. F.e. 20 have different only TypeID but same VendorID and all of them can be represented as Integer, next 10 differ in VendorID And TypeID but all of them can be represented as Short and so on.
It's still not clear why you should have to cast at all. As soon as SOME_TYPE is written into your sourcecode OR the type of set setValue method is hardcoded (in your example int or Integer) you don't need runtime checking - you need compile time checking.
So I suppose the following snippet is how your API users should code:
public class TypeTest {
public static void main(String[] args) {
AType<Integer> type0 = Types.SOME_TYPE_0.instantiate();
type0.setValue(10);
AType<String> type1 = Types.SOME_TYPE_1.instantiate();
type1.setValue("foo");
}
}
I have stripped down your example to the bare minimum which is required to understand the Generics part:
abstract class AType<T> {
private T value;
// standard getter/setter
public T getValue() { return this.value; }
public void setValue(T value) { this.value = value; }
}
class SpecTypeInt extends AType<Integer> {
}
class SpecTypeString extends AType<String> {
}
interface Instantiable<T> {
T instantiate();
}
The key part is: Don't use an enum, because an enum cannot have type parameters. You can use a plain interface instead like the next snippet. Each reference in the interface points to a factory. Each factory knows a) the abstract type and b) the concrete type. To make Generics happy you have to glue a) and b) together with ? extends X.
interface Types {
Instantiable<? extends AType<Integer>> SOME_TYPE_0 = new Instantiable<SpecTypeInt>() {
#Override
public SpecTypeInt instantiate() {
return new SpecTypeInt();
}
};
Instantiable<? extends AType<String>> SOME_TYPE_1 = new Instantiable<SpecTypeString>() {
#Override
public SpecTypeString instantiate() {
return new SpecTypeString();
}
} ;
}
Cleanup: Must your user look into the interface: Yes, he must in any case, because he must know which is the appropriate type for setValue 1. NO solution can circumvent this. Although Eclipse might help you and your users a little bit: In main just type Types.SOME_TYPE_1.instantiate(); then go to the start of the line, hit Ctrl2 + L ("Assign to loccal variable") and Eclipse replaces the AType<String> instantiate = part for you.
1If your users don't know the right type for the setValue method, then you are asking the wrong question. In that case you should have asked something like "How to design a Generic safe conversion facility?".
Maybe using a setValue method like this:
public void setValue(Object value) {
if (value == null)
throw new IllegalArgumentException("Value is mandatory.");
this.value = (T)value;
}
Although you will have an unchecked cast.
Hope this helps