Get static variable of subclass given superclass - java

This was very difficult for me to word into a question so allow me to explain.
I have an abstract class Entity and subclasses House and Warehouse. Each subclass has the same static variables with different values.
When a button is pressed in my game an Action is created which specifies which Entity subclass gets created and placed in the world. I want to write a generic method to place some Entity to the world using the static variables of which ever subclass it is.
I have a class PlaceEntityAction and when the mouse is clicked the appropriate entity will be placed assuming conditions are correct. How can I pass the Class I want to be placed to this Action so it works with any generic Entity?
Here is some dumbed down code:
if (mousePressed)) {
if (some conditions are true) {
int ex = x pos
int ey = y pos
if (world.player.haveFunds(e.COST_ENERGY, e.COST_MONEY,
e.COST_RESOURCE)) {
if (world.places[ex][ey] == 0) {
world.entities.add(e);
world.player.addEnergy(-e.COST_ENERGY);
}
}
}
}
So basically how can I get that e to be whatever subclass I pass to the Action since COST_MONEY, etc is static and should be accessed by the Class and not an object?
I'm really struggling to express what I want. Maybe someone can decipher this or provide some other insight regarding my issue. I can provide any other information necessary if you want.
EDIT:
e is an instance of whichever subclass I previously initialized based on an ID system but I don't like this method.

Static variables are the wrong approach here, especially since you've already instantiated your entity.
Instead, create abstract functions costEnergy(), costMoney(), and so on on the parent class, and implement them (with the correct values) on the child.

Static variables aren't polymorphic in Java. An option would be to declare abstract methods getCostEnergy, getCostMoney and getCostResource in Entity, and have each subclass override those methods to return different constants. Would that work for your scenario?

Related

Why Dynamic Method Dispatch is not working on properties?

public class Main {
public static void main(String[] args) {
Parent p = new Child();
System.out.println(p.x); // 10 is printed
System.out.println(p.print()); // Child is printed
}
}
class Parent{
int x = 10;
public String print(){ return "Parent";}
}
class Child extends Parent{
int x = 55;
public String print(){ return "Child"; }
}
Why Dynamic Method Dispatch is not working on properties ?
Is there any purpose, meaning or it was just designed like that.
Effectively? Because unlike methods, fields cannot be overridden. Fundamentally: It makes no sense.
When you override a method, it is not about just the name. Only if everything matches, does it count. Let's try this:
public class Example {
#Override public boolean equals(Example other) { return false; }
}
The above will not compile because that is not the same as Object's own equals. The parameter type doesn't match. As a language syntax sugar nicety to you, you may 'widen' your specs (you can specify a more specific return type, and a more general parameter type, and you can elect to declare fewer checked exceptions), but if you inspect a class file, you'll find the exact method signature of your parent class in your own.
Expanding that notion to fields, a field isn't just the name. It's the name and its type.
When you declare int x; in class Parent, that field exists in all instances of Parent, including any instances of a subclass of Parent. In other words, your class Child extends Parent class already has an x field. There's nothing you can do to change its essence. That's in sharp contrast to methods, where you can redefine what it does by changing the code. This just doesn't apply to fields: Fields don't have code.
Because of all that, when you declare a method that has the same signature as a method declaration of a parent, that is an override, but:
When you declare a field that has the same signature (same name, same type) as a parent class's field, you are declaring a second, separate field whose name shadows the field of the parent.
The behaviour is just completely different. The simple solution is to simply not declare int x, at all, in child. Write into parent's x, if you must. The above explains why this behaviour is so very different.
Writing classes that participate in an inheritance hierarchy is hard. We need the classes to expose behavior and allow customization by subclasses, but without allowing subclasses to change things the superclass is counting on. Allowing subclasses to override methods, but keeping superclass state private accomplishes this separation.
However, if subclasses can override variables in a superclass then the superclass can’t have confidence in the variables it needs to manipulate and the subclasses can tamper with the superclass. The superclass may work or not, depending on what extends it.
If this was a feature, and you had the option to use it or not, similar to using a keyword like virtual in C# but for methods, when would you use it? I can’t think of a case where it would make sense.

Java: If this is instanceof Something, display a variable that belongs only to Something?

Everything here is renamed and simplified.
I have a parent class (normalThing) with a method that displays some data about the instance, and another class (specialThing) extending the parent to include another instance variable (addedPrice).
I want my display method to say whether or not the instance is a specialThing, and if it is, to display the addedPrice. But because addedPrice belongs only to specialThing, I can't figure out how to code it!
void displayInfo(){
StringBuilder d = new StringBuilder("Am I special? ");
if(this instanceof specialThing){
d.append("Yes, so I cost an extra " + this.addedPrice);
//No, I didn't expect that to work, but I had hope
}
else d.append("Nope.");
JOptionPane.showMessageDialog(null, d);
}
Is there any way to do this without essentially making a "could-be-addedPrice" variable in the normalThing class?
You can achieve this by overriding displayInfo appropriately in child class. That is a better way because parent class should not try to know what are its children because number of child classes and their names are not in the control of parent class. People can extend the parent class in unexpected/unpredictable and uncontrolled manner. It will work well if you define displayInfo contract and enforce the child classes to implement it. Number of child classes does not matter. As long as displayInfo is implemented as per contract, OOP will take care of the rest :-)

how can I change variables in super class

I want to write a program in java that consists of three classes, A, B, and C, such that B extends A and C extends B. Each class defines an instance variable (named "x").
how can I write a method in C to access and set A's version of x to a given value, without changing B or C's version?
I tried super.x but It wasn't true.
any help?
thanks for your attention in advance
You can access A's version of x like this:
((A)this).x
as long as x wasn't declared private in class A. I've just tested it.
Note that for fields, there is no overriding (as there is for methods). Thus, for an object of class C, there will be three x fields, but two of them can't be accessed normally because they are hidden by the other field named x. But casting the object as above will allow you to get at it, if it would have been visible if not hidden.
I think it is very poor practice to declare fields of the same name in a class and its subclasses. It's confusing. It can happen legitimately if, say, you have a class A and you later change the implementation of A and add a new private field z; in that case, it may not be possible to make sure no subclasses of A already have a field z, since you don't even always know what all the subclasses are (if A is a class you've distributed publicly, for instance). I think it's for that reason that Java allows you to have fields of the same name, and why the hiding rules are the way they are, because it allows things like this to work without breaking all the other subclasses. Other than that, though, I recommend not having fields of the same name in superclasses and subclasses. Perhaps if they're all private it might be OK, though.
Do the following
public static void main(String[] args) throws Exception {
C c = new C();
System.out.println("c:" + c.x);
System.out.println("a:" + ((A)c).x);
c.changeAX();
System.out.println("c:" + c.x);
System.out.println("a:" + ((A)c).x);
}
static class A {
int x;
}
static class B extends A {
int x;
}
static class C extends B {
int x;
public void changeAX() {
((A)this).x = 4;
}
}
Fields are resolved relative to the declared type of the reference. The above prints
c:0
a:0
c:0
a:4
The field will have to have at least protected visibility.
You don't want to be hiding class members, it's bad practice because it can easily confuse anyone trying to figure out which member you are referring to.
I misread your question. You can't do what you're trying to do.
Extending classes means adding information in several layers, ultimately resulting in one object. Although there are multiple layers, this doesn't mean that the layers are separate of eachother.
The variable X will be defined at one level (probably A) and after that the other classes will use this variable (if it's declared protected), but they won't have their own copy of it. You can only access your direct superclass.
This class might give you additional access to its own superclass, but you don't have direct contact with the super-super class.

the static concept in java

I can't seem to understand the static key word (java) so I googled it up and viewed a thread in this website, though I'm sure the answer was conclusive and clear -it always is over here- I didn't seem to understand it for two reasons; I'm not a native English speaker and the language was a bit vague for me, and it lacked exemples of use in classes, instance of classes, interfaces (if possible), instance of interfaces and variables, lists and arrays ect.
I would really appreciate any help and please keep the English as simple as possible ;)
Thank you
Aditsan
Note from editor: Please note that the original poster is asking for examples, and is not a native English speaker as you provide answers. From the comments, it appears that OP doesn't understand the concept well enough to ask about the parts that don't make sense yet, so examples would be awesome! It may take extra details and multiple different explanations to find the combination of answers that works best.
I think it helps to understand what non-static means, i.e. field/methods/... that are declared without the keyword static.
Every field declared without the keyword static exists as part of an object. If you have two objects, each of these two objects has a field with possibly different contents:
class X {
int f;
}
X x1 = new X();
X x2 = new X();
x1.f = 5;
x2.f = 10;
// x1.f still is 5
However, static fields exist not per object, but per class. So in the following example, there is only one field g no matter how many (if any!) objects of class Y you have:
class Y {
static int g;
}
Y y1 = new Y();
Y y2 = new Y();
y1.g = 5;
y2.g = 10;
// y1.g is 10, because y1.g and y2.g mean the exact same thing
I personally think accesses to static fields should be made using the class (Y.g) instead of mentioning object instances (y1.g), so that the existence without any object instance is more explicit.
For methods the difference is that non-static methods are associated to an object instance, which can be accesses using this inside the method. When invoking a method declared with void m() you can access non-static (and static) fields of the object it is invoked on (so for x1.m() from the example above you can get to the field containing 5, for x2.m() you can access the field containing 10.
Static methods, however, can be invoked without having a (corresponding?) object around. If the declaration is static void n() inside class Y, you can call this method using Y.n() or y1.n() (if y1 is an instanceof Y, as above). Here, too, I prefer the first way of writing it down. Because in static methods you do not have a reference to the object instance (which is named this in non-static methods), you cannot access specific non-static fields from inside a static method - simply because there is no clear association to a specific object.
Regarding static and class definitions: This is rather advanced. You can declare a class inside another class. If the inner class is not static, every object instance of the inner class also has a reference to an instance of the outer class (which also means that you only can create an instance of the inner class if you have an instance of the outer class). This is not always what you want. By declaring the inner class static it just exists and can be used, more or less, like a class defined in its own file.
Basically, static implies/provides two things:
1) Only one instance of an "item" exists in the whole system (JVM)
2) Static "items" are also context/state free
To explain (1) above: Suppose you have a Meal Token issuer. No matter how many users/processes are there in the system, all tokens must be issued by a single "thing". You would develop that "thing" as static. You would then decide what that "thing" is. It could be a class that does a complex operation and implements a complex business rule. Then you would have a single static class issuing tokens in "a single uniform way" for the whole system. Some times, all that matters is that the token should be "static" but how it is issued could be non-static. Then you would simply implement a "Static" token counter.
To explain (2) : Going by what is said for (1) above, you can easily see why it is important that the static "things" operate in a context-free manner. That is, they do not know who calls them or for what purpose. When they are called, they do not borrow anything from the past, they need all inputs from the current caller, and they just do their job, and remember nothing for the future.

Java - Class Variable

I have a variable: Abstract a. It is a class that extends the Abstract class. However, I need to cast this Abstract variable into a more specific class variable that extends the Abstract class.
My situation: I have two classes, Class1 and Class2 that both extend the Abstract class with methods implemented in each one. I now have an Abstract class variable to work with. I do not know if it is Class1 or Class2, so I cannot simply do a (Class1) a or a (Class2) a (casting).
So how would I successfully cast this variable so that I can use the inner methods?
I was thinking along the lines of using a.getClass().getName() to determine how to cast it, but I am stuck from here on out.
Your new question appears to be asking how to dynamically cast a variable to an arbitrary type unknown at runtime. This is probably a duplicate of java: how can i do dynamic casting of a variable from one type to another? but to summarize, this is not (easily) possible, isn't recommended, and speaks to other issues in your code.
Think about it this way, what variable would you possibly be able to use to store your newly cast object? Imagine if we had a (child) cast operation in Java, that took a variable defined as a parent class, and cast it down to its child (e.g. List -> LinkedList):
public static void func(Abstract a){
???? var = (child)a;
// Do something with var?
}
Notice that 1) there's no way you could ever specify a type for var, since we don't know at runtime what type it will be; and 2) there's nothing we'd be able to do with var beyond the behavior defined in Abstract anyways, because the compiler can't predict which methods will be availible to var other than what's available to Abstract.
If you need to implement class-specific behavior, you should do so inside the class. Have an abstract method which each class has to implement, and which can do whatever you need them to do. Or, if you cannot ensure that, don't define a function that takes an Abstract as an argument; instead define however many functions that take Class1, Class2, etc. objects as parameters, like so:
Abstract method to require all child classes behave similarly
public abstract class Abstract{
/** Do the class-specific behavior you want to do currently in func */
public abstract void operation();
public static void func(Abstract a){
a.operation();
}
}
Functions only for classes that can actually handle what you want
public static void func(Class1 a){
// do something
}
public static void func(Class2 a){
// do something
}
Again, if neither of these options are viable for you (and of course, blocks of instanceof calls aren't acceptable) then I'd be willing to bet money there's something structural in the way you're using Java that's fundamentally incorrect. If you want to post a code sample of exactly what you're trying to accomplish by child-casting, perhaps we can shed some light as to what the issue is.
Leaving this here for posterity - OP's original question asked about creating new instances of an object cast as its abstract parent.
Pretty straightforward, get the object's class object, and create a new instance. For more complex constructors, see the Java documentation on creating new instances dynamically.
public class ClassVar
{
public static abstract class Abstract
{
}
public static class Class1 extends Abstract
{
}
public static class Class2 extends Abstract
{
}
/**
* Given an instance of a child of Abstract, returns a new instance
* of the same class
*/
public static Abstract newInstance(Abstract obj) throws InstantiationException, IllegalAccessException
{
return obj.getClass().newInstance();
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException
{
System.out.println(newInstance(new Class1()).getClass());
System.out.println(newInstance(new Class2()).getClass());
}
}
Result:
class ClassVar$Class1
class ClassVar$Class2
Basically you can use reflection by using
Class cl = ...
cl.newInstance()
The more 'expanded' answer you can find here
Since you edited your question again 3h ago at the time of writing here's my second answer to a problem I thought was solved. It's obvious nobody got what you're really asking for in the first place. Try to improve how you're asking questions.
However, the answer is simple:
From the point of view of object orientation you simply shouldn't have to (Liskov Substitution principle). Even if you have exact knowledge about exactly two possible instances, you should look for a better approach for the problem you are trying to model.
If you have to, determine the class name and check for equality or carry an extra identifier and compare that one. Implementation couldn't be simpler.

Categories