So the issue I'm running into is this. I've written a method as a part of a program that I'm using to display all the objects in an ArrayList. There are three different types of objects stored in this ArrayList: Fungus, Flowers and Weeds. I'm able to call plantList.get(i).getName() and plantList.get(i).getColor methods with no issue. Both of these variables belong to the parent class called Plant. However, when calling the following method plantList.get(i).getPoison() (this method belongs to the subclass Fungus) I get a compiler error saying that it cannot find the variable Fungus.
I've tried it with every other variable unique to a subclass, and the same things happens. So I can access variables from the parent class 'Plant' but not from any of the subclasses of 'Fungus' 'Flower' or 'Weed'. I'm new to using subclasses and superclasses so I'm having a hard time figuring out exactly where the issue is arising.
public static void displayPlant(ArrayList<Plant> plantList) {
for (int i = 0; i < plantList.size(); i++) {
System.out.print(plantList.get(i).getName());
System.out.print(plantList.get(i).getID());
System.out.print(plantList.get(i).getColor());
if (plantList.get(i).contains(Fungus) == true) {
System.out.print(plantList.get(i).getPoison());
}
else if (plantList.get(i).contains(Flower) == true) {
System.out.print(plantList.get(i).getSmell());
System.out.print(plantList.get(i).getThorns());
}
else {
System.out.print(plantList.get(i).getPoison());
System.out.print(plantList.get(i).getEdible());
System.out.print(plantList.get(i).getMedicinal());
}
}
}
A good solution is to use dynamic dispatch. I.e. let the element itself decide what information it wants to print.
class Plant {
...
public String toString() {
return String.join(" ", getName(), getID(), getColor());
}
}
class Fungus extends Plant {
...
#Override
public String toString() {
return String.join(" ", super.toString(), getPoison());
}
}
class Flower extends Plant {
...
#Override
public String toString() {
return String.join(" ", super.toString(), getSmell(), getThorns());
}
}
class Weed extends Plant {
...
#Override
public String toString() {
return String.join(" ", super.toString(), getPoison(), getEdible(), getMedicinal());
}
}
Your loop will look like this:
public static void displayPlant(ArrayList<Plant> plantList) {
for(Plant p : plantList)
System.out.println(p); // This calls toString
}
Actually you are doing it in a wrong way,
Once you keep the object of child class into parent class variable then at compile time it search or find only the methods and variables that are declared in the parent class.
if you want to access the child class variables then you need to first find out the child class and then typecast it according
public static void displayPlant(ArrayList<Plant> plantList) {
for (int i = 0; i < plantList.size(); i++) {
Plant plant=plantList.get(i);
if (plant instanceof Flowers) {
Flowers fl=(Flowers)plant;
//TODO do whatever you want to do
}
else if(plant instanceof Weeds) {
Weeds wd=(Weeds)plant;
//TODO do whatever you want to do
}else if (plant instanceof Fungus) {
Fungus wd=(Fungus)plant;
//TODO do whatever you want to do
}
}
I hope it help you out. Thanks
Java is strongly typed language. That means that, if you want to use methods of child class you have to cast down to child class.
In your example:
...
else if (plantList.get(i) instanceof Fungus) { //check if plant is fungus
System.out.print(plantList.get(i).getSmell());
System.out.print(((Fungus)plantList.get(i)).getThorns()); //downcasting
}
...
Your check using constains wouldn't work. To check type of object you need to use operator instanceof.
Related
Code first - question later
class A {
int value() { return 1; } //The value
int getThisValue() { return this.value(); } //gives back the overridden value
int getValue() { return value(); } //this too
int getSuperValue() { return value(); } //for overriding in B
final int getSuperValue2() { return getSuperValue(); }
//Here I get the not-overridden value
//TODO: simplify the process of getting the un-overridden value
}
class B extends A {
#Override
final int getSuperValue() { return super.value(); } //returns the correct value
}
public class Test extends B{
#Override
int value() { return 3; } //overriding the value
public static void main(String[] args) { //output
Test test = new Test();
System.out.println("getValue(): " + test.getValue()); //3
System.out.println("getThisValue(): " + test.getThisValue()); //3
System.out.println("getSuperValue(): " + test.getSuperValue()); //1
System.out.println("getSuperValue2(): " + test.getSuperValue2()); //1
}
}
I have A class, in which I access value.
This value gets overridden
-> I want to access the un-overrridden value in A
My Question: Is getSuperValue2() the only way get the un-overridden value or is there another way?
I want to know if I can protect my Code, by only accessing Code I know, but making my code overrideable for those, that want to change the functionality a bit
There is indeed no way once a subclass starts overriding. That's by design - you don't get to refer to "The implementation of the getValue() method the way class A does it", that's the wrong mental model. You merely get to refer to the notion of "the implementation of the getValue() method the way this object does it" (note the difference: Think 'objects', not 'classes'). Once we talk solely about 'the impl from this object', then the idea of "But I want the unoverridden value" no longer makes any sense, hence why you can't do it.
want to know if I can protect my Code
Yeah of course. Just mark the method final! This is a sometimes-observed pattern:
public class Parent {
public final void init() {
childInit();
doStuffThatChildClassesCannotStopFromHappening();
}
protected void childInit() {
// does nothing - child classes can override if they wish
}
}
I work with XML doc. There are a lot of similar tags and methods in my programm. All they do the same things but all they return and have as parameters different objects. Inside this method I check two String. So, can use T instead different objects. All this objects not connected. For example, I want to do the following:
private <T> T checkBusinessEntityTypeCode(CheckDtKdt checkDtKdt, T kdtCode, T dtCode) {
if (kdtCode != null && dtCode != null) {
if (StringUtils.compare(kdtCode..getValue(), dtCode.getValue()) != 0) {
checkFieldsDtKdtService.save14Graph(checkDtKdt, dtCode.getValue(), kdtCode.getValue());
dtCode.setValue(kdtCode.getValue());
}
if (StringUtils.compare(kdtCode.getCodeListId(), dtCode.getCodeListId()) != 0) {
checkFieldsDtKdtService.save14Graph(checkDtKdt, dtCode.getCodeListId(), kdtCode.getCodeListId());
dtCode.setCodeListId(kdtCode.getCodeListId());
}
}
}
Of course, this code doesn't work. Because of get() and set() method. Can I use something like that?
You can use the Java Upper Bound Generics for example you can write a super class where you put an inherited or abstract get and set methods :
private <T extends ApplicationController> T checkBusinessEntityTypeCode(String checkDtKdt, T kdtCode, T dtCode){.... }
ApplicationController is our Superclass (can be an interface) , all "T" classes inherit from it so all references from any T can call the get and set methods .
Just be carefull you need to read more about upper and lower bound generics before using it , using bounds with Collections make the collections immutables with many other tricks ...
Link to Oracle documentation : https://docs.oracle.com/javase/tutorial/java/generics/bounded.html
you can read This answer from StackOverFlow :
Understanding bounded generics in java. What is the point?
---------------------------------------------------
Your code compile in my IDE and i can call methods of GvtApplicationController with the reference kdtCode(compile time) :
private <T extends GvtApplicationController> T checkBusinessEntityTypeCode(String checkDtKdt, T kdtCode, T dtCode) {
if (kdtCode != null && dtCode != null) {
kdtCode.getCurrentVersionPath();
}
return dtCode;
}
Example :
abstract class Person{
public abstract String getName();
}
class Student extends Person{
#Override
public String getName() {
return "MyName";
}
}
class GenericsBounder{
public static<T extends Person> String showName(T t){
return t.getName();
}
}
public class Bounder{
public static void main(String[] args) {
String s= GenericsBounder.showName(new Student());
System.out.println(s);
}
}
Output :
|MyName
I have two ArrayLists - ArrayList1 and ArrayList2. Each of them is filled with objects - Object1 and Object2, respectively.
Both of these objects have method 'getText'.
Object1:
public String getText() { return "1";}
Object2:
public String getText() { return "2";}
At certain point I would like to loop through each of these lists using the same method (just with different parameter).
loopThroughList(1)
loopThroughList(2)
What is the syntax if I want to call a method, but I don't know which object it is going to be? This is the code I have so far:
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getText());
}
It says Cannot resolve method getText. I googled around and found another solution:
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getClass().getMethod("getText"));
}
But this gives me NoSuchMethodException error. Even though the 'getText' method is public.
EDIT: To get the correct list, I am calling the method 'getList' of a different object (lists) that returns either ArrayList1 or ArrayList2 (depending on the provided parameter).
class Lists
public getList(list) {
if (list == 1) {
return ArrayList1;
}
else if (list == 2) {
return ArrayList2;
}
}
Define an interface for the getText method
public interface YourInterface {
String getText();
}
Implement the interface on the respective classes
public class Object1 implements YourInterface {
#Override
public String getText() {
return "1";
}
}
public class Object2 implements YourInterface {
#Override
public String getText() {
return "2";
}
}
Modify your getList method to return List<YourInterface>
public static List<YourInterface> getList(int list){
List<YourInterface> result = new ArrayList<>();
if(list == 1){
// your initial type
List<Object1> firstList = new ArrayList<>();
result.addAll(firstList);
} else {
// your initial type
List<Object2> secondList = new ArrayList<>();
result.addAll(secondList);
}
return result;
}
Declaration for loopThroughList
public static void loopThroughList(List<YourInterface> list){
list.forEach(yourInterface -> System.out.println(yourInterface.getText()));
}
Sample usage.
public static void main(String[] args) {
loopThroughList(getList(1));
loopThroughList(getList(2));
}
Interfaces work great here, but there a couple of other options if you're dealing with legacy code and cannot use interfaces.
First would be to cast the list items into their respective types:
for (Object o : lists.getList(listNumber)) {
if(o instanceof Object1) {
Object1 o1 = (Object1)o;
System.out.println(o1.getText());
}
else if(o instanceof Object2) {
Object1 o2 = (Object2)o;
System.out.println(o2.getText());
}
else {
System.out.println("Unknown class");
}
}
You can also use reflection to see if the object has a getText method and then invoke it:
for (Object o : lists.getList(listNumber)) {
try {
System.out.println(o.getClass().getDeclaredMethod("getName").invoke(o));
}
catch(Exception e) {
System.out.println("Object doesn't have getText method");
}
}
This is awful. Can you elaborate on what specifically you are trying to do? Java is strong typed by design, and you are trying to get around it. Why? Instead of Object, use the specific class, or interface as previously suggested. If that's not possible, and you must use lists of Objects, use instanceof and casting eg:
for (Object o : lists.getList(listNumber)) {
if (o instanceof Object1) {
Object1 o1 = (Object1) o;
System.out.println(o1.getText());
} else if (o instanceof Object2) {
Object2 o2 = (Object2) o;
System.out.println(o2.getText());
}
}
This is where interfaces come in.
interface HasText {
public String getText();
}
class Object1 implements HasText {
#Override
public String getText() {
return "1";
}
}
class Object2 implements HasText {
#Override
public String getText() {
return "2";
}
}
private void test() {
List<HasText> list = Arrays.asList(new Object1(), new Object2());
for (HasText ht : list) {
System.out.println(ht);
}
}
If one of your objects is not in your control you can use a Wrapper class.
class Object3DoesNotImplementHasText {
public String getText() {
return "3";
}
}
class Object3Wrapper implements HasText{
final Object3DoesNotImplementHasText it;
public Object3Wrapper(Object3DoesNotImplementHasText it) {
this.it = it;
}
#Override
public String getText() {
return it.getText();
}
}
private void test() {
List<HasText> list = Arrays.asList(new Object1(), new Object2(), new Object3Wrapper(new Object3DoesNotImplementHasText()));
for (HasText ht : list) {
System.out.println(ht);
}
}
Just to add more to this answer and give you some more to think on this (Will try to do it in a simple, non-formal way). Using interfaces is the proper way of doing such operation. However, I want to stand on the "bad idea":
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getClass().getMethod("getText"));
}
What you are doing here, is using a mechanism called Reflection:
Reflection is a feature in the Java programming language. It allows an
executing Java program to examine or "introspect" upon itself, and
manipulate internal properties of the program. For example, it's
possible for a Java class to obtain the names of all its members and
display them.
What you actually attempted, is using that mechanism, to retrieve the method through a Class reflection object instance of your Class (sounds weird, isn't it?).
From that perspective, you need to think that, if you want to invoke your method, you now have, in a sense, a meta-Class instance to manipulate your objects. Think of it like an Object that is one step above your Objects (Similarly to a dream inside a dream, in Inception). In that sense, you need to retrieve the method, and then invoke it in a different (meta-like) way:
java.lang.reflect.Method m = o.getClass().getMethod("getText");
m.invoke(o);
Using that logic, you could possibly iterate through the object list, check if method exists, then invoke your method.
This is though a bad, BAD idea.
Why? Well, the answer relies on reflection itself: reflection is directly associated with runtime - i.e. when the program executes, practically doing all things at runtime, bypassing the compilation world.
In other words, by doing this, you are bypassing the compilation error mechanism of Java, allowing such errors happen in runtime. This can lead to unstable behavior of the program while executing - apart from the performance overhead using Reflection, which will not analyze here.
Side note: While using reflection will require the usage of Checked Exception handling, it still is not a good idea of doing this - as you practically try to duck tape a bad solution.
On the other hand, you can follow the Inheritance mechanism of Java through Classes and Interfaces - define an interface with your method (let's call it Textable), make sure that your classes implement it, and then use it as your base object in your list declaration (#alexrolea has implemented this in his answer, as also #OldCurmudgeon has).
This way, your program will still make the method call decision making at Runtime (via a mechanism called late binding), but you will not bypass the compilation error mechanism of Java. Think about it: what would happen if you define a Textable implementation without providing the class - a compile error! And what if you set a non-Textable object into the list of Textables? Guess what! A compile error again. And the list goes on....
In general, avoid using Reflection when you are able to do so. Reflection is useful in some cases that you need to handle your program in such a meta-way and there is no other way of making such things. This is not the case though.
UPDATE: As suggested by some answers, you can use instanceof to check if you have a specific Class object instance that contains your method, then invoke respectively. While this seems a simple solution, it is bad in terms of scaling: what if you have 1000 different classes that implement the same method you want to call?
your objects have to implement a common interface.
interface GetTextable {
String getText();
}
class One implements GetTextable {
private final String text;
public One(final String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
class Two implements GetTextable {
private final String text;
public Two(final String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
#Test
public void shouldIterate() throws Exception {
List<GetTextable> toIterate = Arrays.asList(new One("oneText"), new Two("twoText"));
for(GetTextable obj: toIterate) {
System.out.println(obj.getText());
}
}
In my application I have a 2d array of entities to represent a grid. Each location in the grid can either be empty or occupied by an entity (in this case it's just a person or wall). Right now I use instanceof to check whether an entity is a person or a wall.
I was thinking of giving each entity a method which returns an enum stating their type so i.e. a wall entity would return EntityType.WALL. I was wondering if this is the best idea to remove the use of instanceof or is instanceof suitable in this scenario?
Use Tell, Don't Ask: instead of asking the objects what they are and then reacting on that, tell the object what to do and then walls or people do decide how they do what they need to do.
For example:
Instead of having something like this:
public class Wall {
// ...
}
public class Person {
// ...
}
// later
public class moveTo(Position pos) {
Object whatIsThere = pos.whatIsThere();
if (whatIsThere instanceof Wall) {
System.err.println("You cannot move into a wall");
}
else if (whatIsThere instanceof Person) {
System.err.println("You bump into " + person.getName());
}
// many more else branches...
}
do something like this:
public interface DungeonFeature {
void moveInto();
}
public class Wall implements DungeonFeature {
#Override
public void moveInto() {
System.err.println("You bump into a wall");
}
// ...
}
public class Person implements DungeonFeature {
private String name;
#Override
public void moveInto() {
System.err.println("You bump into " + name);
}
// ...
}
// and later
public void moveTo(Position pos) {
DungeonFeature df = currentPosition();
df.moveTo(pos);
}
This has some advantages.
First, you don't need to adjust a giant if then else tree each time you add a new dungeon feature.
Second, the code in the dungeon features is self-contained, the logic is all in the said object. You can easily test it and move it.
The theoretical solution to removing the instanceof in a refined way is the usage of the Visitor Pattern. How it works is that the object that needs to know whether the other element is a wall or person calls that object with itself as a parameter, and that particular object calls back thus providing information about its type.
Example,
public class Person {
void magic() {
if(grid.getAdjacent() instanceof Person) {
Person otherPerson = (Person)grid.getAdjacent();
doSomethingWith(otherPerson);
} else if(grid.getAdjacent() instanceof Wall) {
Wall wall = (Wall)grid.getAdjacent();
doOtherThingWith(wall);
}
}
}
Can become
public class Person extends Entity {
void magic() {
grid.getAdjacent().visit(this);
}
void onVisit(Wall wall) {
doOtherThingWith(wall);
}
void onVisit(Person person) {
doSomethingWith(person);
}
public void visit(Person person) {
person.onVisit(this);
}
}
public class Wall extends Entity {
public void visit(Person person) {
person.onVisit(this);
}
}
I would let person and wall inherit from a abstract superclass ( e.g. Tile ) which has a method getType() returning an enum or int and implement this method in Wall and Person returning the appropriate
If you follow the other answers here and implement a visitor pattern or use an enum you will not make a mistake.
However, it might also help to think about what exactly it is you want to do with that switching logic (be it instanceof or visitors), because sometimes there is a simpler way to do that.
For example, if all you want to do is check if an entity occupies a grid in a blocking way, then you can just add a method boolean isSolid() to each entity via interface. You can use this with default methods for extra beauty:
public interface GridPhysics {
default boolean isSolid() {
return true;
}
// other grid physics stuff
}
public class Wall implements GridPhysics {
// nothing to do here, it uses the default
}
// in your game logic
public boolean canMoveTo(GridPhysics gridCell) {
return !gridCell.isSolid() && otherChecks();
}
You might also want to have a look at entity component systems (e.g. Artemis), which basically take this idea of "composition over inheritance" to the extreme.
ligi's answer is right on the money. (Whoever downvoted it, I wonder what they were thinking.) As an alternative, consider this:
abstract class Tile
{
public final EntityType type;
protected Tile( EntityType type )
{
this.type = type;
}
}
abstract class Pedestrian extends Tile
{
public Pedestrian()
{
super( EntityType.PEDESTRIAN );
}
}
abstract class Wall extends Tile
{
public Wall()
{
super( EntityType.WALL );
}
}
The rationale behind this is that the "type" of the entity is a permanent characteristic of the entity, so it is suitable to be specified in the constructor and to be realized in a final member field. If it is returned by a virtual method (non-final method in java parlance) then descendants would be free to return one value at one point in time, and another value at another point in time, which would spell havoc.
Oh, and if you really cannot stand the public final member, go ahead and add a getter for it, but my advice would be that never mind the purists, public final members without getters are perfectly fine.
Answers are very good here nothing to say anything about that, but if I were in such situation and if it is allowed than i would have been gone for a 2d int array with possible value 0(for empty by default assignment) and 1,2 for person or wall.
As mentioned on this other question, modern Java compilers are very efficient at operations like instanceof. You should be fine using it.
In fact, one of the other provided answers tested instanceOf and string comparisons, and instanceOf was significantly faster. I recommend you stick with using it.
I have 3 class and, first is Person :
public class Person {
Person() {
}
}
Second is Engineer that extends of Person
public class Engineer extends Person {
Engineer() {
}
}
and another extends of Person
public class Doctor extends Person {
Doctor() {
}
}
Last one is Work that take in constructor an object Person
public class Work {
Work(Person p) {
//how to insure that p is Engineer ?
}
}
How to detect that an object p is Engeneer and not from another class ?
You can use the instanceof keyword for checking the type of an object. It works like this
if(p instanceof Engineer) {
// do Engineer stuff
} else {
// not an Engineer object
}
You can check it with the following:
if (p instanceof Engineer)
or
if (p.getClass() == Engineer.class)
Use something like:
if (p.getClass() == Engineer.class) {
//Is engineer
}
p.getClass()
(and from there, .getName())
or the operator instanceof (note, a Doctor and an Engineer will be return instanceOf Person as true; check for the more specific class)
You shouldn't need to do this.
Work(Engineer p) {
// p is an Engineer
}
or
Work(Person p) {
p.doWork(); // calls the appropriate work methopd for any person.
}
public class Work {
// ensure only Engineer can pass in
Work(Engineer p) {
}
}
or using instanceof keyword
The instanceof operator compares an object to a specified type. You
can use it to test if an object is an instance of a class, an instance
of a subclass, or an instance of a class that implements a particular
interface.
public class Work {
Work(Person p) {
// make sure p is type of Engineer
if(p instanceof Engineer) {
// dowork
Engineer e = (Engineer) p;
} else {
// not engineer or p is null
}
}
}
Use instanceof keyword like
if(p instanceof Engineer) {
// do something
}
if(p instanceof Doctor) {
// do something
}
but this is not right way,
you should have Enginner's behavior(method) in Engineer's class and Doctor's behavior in Doctor class.
See Peter's answer, Runtime polymorphism will detect which method to call automatically.
i.e.
class Engineer extends Person {
// properties
// methods
public void doWork() {
// does engineering work
}
}
class Doctor extends Person {
// properties
// methods
public void doWork() {
// does doctor work like check patients, operation or other his task
}
}
class Work {
Work(Person p) {
p.doWork(); // if you pass engineer obj here, Engineer.doWork() is called. And if you pass doctor, Doctor.doWork() is called.
// You don't need to use instanceof.
}
}
Engineer and Doctor have same method names in above case but in some cases you may need to use instanceof, for e.g. Doctor will have checkPatient() method, Engineer will have some different method name like designEngine(), then you will have to use instanceof.