Method is undefined for a class - java

I am trying to run a code in eclipse that uses a method called getArea(an object). I am currently getting an error saying
The method getArea(ComparableRectangle) is undefined for the type RectangleTest
This is the code for RectangleTest-
package geometry;
import java.awt.Rectangle;
public class RectangleTest extends Rectangle {
/**
*
*/
private static final long serialVersionUID = -3282103336310735942L;
public static void main(String args[]) {
ComparableRectangle rect01 = new ComparableRectangle(5, 4);
ComparableRectangle rect02 = new ComparableRectangle(6, 8);
System.out.println("Area: " + getArea(rect01));
}
}
And this is the code for ComparableRectangle.
package geometry;
import java.awt.Rectangle;
public class ComparableRectangle extends Rectangle implements Comparable {
private int width;
private int height;
public ComparableRectangle(int w, int h) {
width = w;
height = h;
}
public double getArea(ComparableRectangle rect) {
return width*height;
}
public boolean compareTo(ComparableRectangle rect1, ComparableRectangle rect2) {
if(rect1.width == rect2.width && rect1.height == rect2.height) {
return true;
}
else {
return false;
}
}
#Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
}
}
How do I clarify that rect01 is a ComparableRectangle?

In object oriented language like Java or C++ to call a class method you need a instance of that class, which we call also an object instantiated from that class. So you have to call your method like below:-
rect02.getArea(rect01);
rect01.getArea(rect02);
Because getArea(ComparableRectangle rect) is a member function or method of class ComparableRectangle hence you need its instance to call it. Here are two instances of that class rect01 and rect02.
Good luck!

You misunderstood how methods and their parameters work.
You need some way to combine the method with some object it should be called on. Currently you do so by using the object as parameter, but this is not correct.
You should combine object and method by writing
obj.method();
Therefore, you should call the method like
rect01.getArea();
and remove the parameter from the method
public double getArea() { ... }
Parameters can be used to give the method additional information on the way. A good example is the compareTo method which is supposed to compare the current instance with the given instance. A call would look like
rect01.compareTo(rect02);
and the methods signature is
public int compareTo(Object o)
Note that it only has one parameter as the current instance is implicitly known to the method (this keyword).
Notes
There is no need for the additional custom compareTo method, which by the way should be named compare and should be static since it's not bound to any instance.
Also note that your custom compareTomethod is not comparing. It just returns same or not same. But for an order you need less than, greater than and equals. Your method thus does not define an order.

Related

List of non-static method references in Java

I am trying to use a list of function references as a lookup table (avoiding the need for a long switch statement). The code worked for a list of static methods, but when I tried to use non-static (i.e. instance) methods in the list, Java gives several errors regarding the types not matching.
Here is a minimal example:
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
public class MethodReferences {
// My original list of static references
private final static List<Function<Integer, Integer>> lookupTable = Arrays.asList(MethodReferences::f1, MethodReferences::f2);
// This doesn't work
// private final List<Function<Integer, Integer>> lookupTable = Arrays.asList(MethodReferences::f3, MethodReferences::f4);
private static int f1(int x) { return x * 2; }
private static int f2(int x) { return x * 3; }
private int f3(int x) { return x * 2; }
private int f4(int x) { return x * 3; }
public void run() {
System.out.println(lookupTable.get(1).apply(3));
}
public static void main(String[] args) {
MethodReferences testClass = new MethodReferences();
testClass.run();
}
}
The errors I received were all for the line containing the non-static definition:
Type mismatch: cannot convert from List<Object> to List<Function<Integer,Integer>>
and:
The target type of this expression must be a functional interface
I tried using this:: instead of MethodReferences:: before the function names. The code then compiled, but when it runs, nothing happens, probably because this has to be used within non-static functions.
I then moved the initialisation of the array (still using this:: to within the class constructor, but it continued to produce no output when run.
I've checked through the documentation and tutorials on method references in Java, but I cannot find an examples of creating references to instance methods within the class it is defined in (and I cannot find any examples of lists of function references either).
I'm aware that in the main method, you can do testClass::f1, but for my specific situation (not the example code) I do not even have a main class (the class is instantiated by another library), so this approach isn't possible. The methods have to be non-static because I need to be able to modify instance variables within them.
Edit:
It turns out that using this:: does work for the example code, although I am still unsure as to why it is valid (surely you can only use this within a non-static function?)
You need to use BiFunction instead of Function. The first argument is the implicit this argument.
public class MethodReferences {
private final static List<BiFunction<MethodReferences, Integer, Integer>> lookupTable
= Arrays.asList(MethodReferences::f3, MethodReferences::f4);
private int f3(int x) { return x * 2; }
private int f4(int x) { return x * 3; }
public void run() {
System.out.println(lookupTable.get(1).apply(this, 3));
}
public static void main(String[] args) {
MethodReferences testClass = new MethodReferences();
testClass.run();
}
}
output:
9
For instance method references which use the ClassName::functionName format, instead of instanceName::functionName, you also need to pass the specific instance of the class to the function when calling .apply().
This means that your method references are actually need to be a BiFunction<MethodReferences, Integer, Integer>, even though there is only one explicit parameter to the function.
When calling the method, you also need to pass this into apply:
import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
public class MethodReferences {
// To refer to non-static methods by class name,
// you must pass in the instance explicitly:
private final List<BiFunction<MethodReferences, Integer, Integer>> lookupTable = Arrays.asList(MethodReferences::f3, MethodReferences::f4);
private int f3(int x) {
return x * 2;
}
private int f4(int x) {
return x * 3;
}
public void run() {
// We need to pass this in, because it isn't implicit
// for ClassName::functionName references:
System.out.println(lookupTable.get(1).apply(3));
}
public static void main(String[] args) {
MethodReferences testClass = new MethodReferences();
testClass.run();
}
}

Java subclass with different method parameters

I am trying to make a simulation that simulates simple creatures and carnivorous creatures.
I have a class called creature and a subclass called carnCreature. I have a method in creature called eat, that takes in a one type of object, but I need the eat method in the carnCreature class to take in a list of creatures. I tried naming the method the same as it is named in the creature class, but when I try to call it, java doesn't accept the updated parameters.
package simulationObjects;
import java.awt.Color;
import java.util.List;
import java.util.Random;
import java.lang.Math.*;
public class Creature {
public int x;
public int y;
public int maxTilesX;
public int maxTilesY;
public Color color;
public float health = 50;
public int life = 0;
public Creature (int x, int y, Color color, int maxTilesX, int maxTilesY) {
this.x = x;
this.y = y;
this.color = color;
this.maxTilesX = maxTilesX;
this.maxTilesY = maxTilesY;
}
public void update(Tile tile) {
eat(tile);
life++;
health-=1;
}
public void eat(Tile currentTile) {
if (currentTile.color == this.color) {
health += 3;
currentTile.color = Color.GRAY;
}
}
public boolean isCarnivore() {
return false;
}
}
package simulationObjects;
import java.awt.Color;
import java.util.List;
public class CarnCreature extends Creature{
private static final boolean CANABOLIC = false;
public CarnCreature(int x, int y, Color color, int maxTilesX, int maxTilesY) {
super(x, y, color, maxTilesX, maxTilesY);
// TODO Auto-generated constructor stub
}
public void update(List<Creature> creatures) {
eat(creatures);
life++;
health-=1;
}
public void eat(List<Creature> creatures) {
for (Creature creature : creatures) {
if (CANABOLIC) {
if (creature.color == this.color) {
health += 3;
creature.health = 0;
}
} else {
if (creature.color == this.color && creature.isCarnivore() == false) {
health += 3;
creature.health = 0;
}
}
}
}
public boolean isCarnivore() {
return true;
}
}
The eat function is being called later like this:
for (Creature creature : creatures) {
if (creature.isCarnivore()) {
creature.upadte(creatures);
} else {
creature.update(tiles.get(creature.x).get(creature.y));
}
}
I am trying to store the creatures and the carnCreatures in the same list, "creatures." Is this the problem, and do I need to store them in separate lists?
Thanks
You have a two options:
Once you know if the creature is carnivore cast it and access the method
Create a method with the same "signature", that is, same name AND arguments.
The second option is the more elegant. Using the "magic" of polymorphism each class will have its method called and you won't need to check the class with the isCarnivore() method. But you will need to get the list of creatures from the tile.
The isCarnivore() test will not spare you to cast to the subclass type as you manipulate as declared type the Creature the base class :
for (Creature creature : creatures) {
if (creature.isCarnivore()) {
((CarnCreature)creature).update(creatures);
} else {
creature.update(tiles.get(creature.x).get(creature.y));
}
}
So the isCarnivore() appear helpless as if (instanceof CarnCreature) would have the same effect and consequences.
Is this the problem, and do I need to store them in separate lists?
It would be better as you don't want manipulate them in an uniform way.
Using the base class to group them in a unique List make your task harder.
But in fact you have a deeper issue. Here eat() is not a overrided method but an overloaded method in the subclass. Same thing for update().
It means that in both cases the two methods are defined in the subclass.
Such a design will not allow to benefit from a polymorphism feature because you want to invoke the first method on the base class instance and invoke the overloaded method on the subclass instance.
In terms of concept, a carnivore creature IS not a creature. Their type of behavior is very different : one consumes a thing (a tile) and the other consumes a very different thing (a list of creature).
To benefit from polymorphism you should re-design the base class and the subclass to override the methods and not overload them. But as you pass really different types in the parameters, you are stuck.
So in your case I think that I would not even create a inheritancy relation between theses classes.

In java, how can you make a method that classifies an object based on previous methods?

I'm working on a lab for AP Comp Sci that includes a vector class and and Quadrilateral class. The vector class constructs vectors and the quadrilateral class constructs a quadrilateral from 4 vectors, and then is supposed to classify the type of quadrilateral. To do this I'm testing for each individual shape it could be with code like
public boolean isParallelogram()
{
if(side1.isParallel(side3) && side2.isParallel(side4))
{
return true;
}
else
{
return false;
}
}
then when it gets to the point to return a classification for the quadrilateral I'm unable to use these methods and what they return because "non static method __________ cannot be referenced in a static context". how can I classify it if I can't access these methods because that quadrilateral object does not exist always? This is my current classify method,
public static String classify()
{
System.out.print("quadrilateral");
return "quadrilateral";
if(Quadrilateral.isParallelogram() == true)
{
System.out.print(" - parallelogram");
return " - parallelogram";
}
}
static methods cannot be called by non-static methods. What I believe is that you have a class Vector. You can have class Quadrilateral something like:
public class Quadrilateral {
private List<Vector> sides;
public Quadrilateral(List<Vector> sides){
this.sides = sides;
}
// Have non-static methods
public classify() {}
public isParallelogram() {}
}
Now you instantiate Quadrilateral and Vector class in some other class and use them like:
Vector side1 = new Vector()
Vector side2 = new Vector() // create two more vector objects
Quadrilateral quadrilateral = new
Quadrilateral(Arrays.asList(side1,side2,side3,side4));
Then you can call classify() on this quadrilateral object. Hope this helps.
If you want to invoke the method directly from the class, it shall be declared as static:
public static boolean isParallelogram()
However, if the method is not to be associated to the class, but to individual objects, you need to instantiate the object first (In this case, your method does not need to be static).
Quadrilateral quad = new Quadrilateral(); //instantiate first
if(quad.isParallelogram()){
//do whatever
}
To me isParallelogram() does not look like a class method anyway, so you may choose 2nd opotion, i.e. instantiate the object first before invoking its method.
But if classify is a behaviour of class Quadrilateral. Then it shall look like:
//Assuming this method checks itself whether it is a quadtrilateral or parallelogram
public String classify() //no static declaration
{
if(this.isParallelogram()){ //apply the check on itself
System.out.print("parallelogram");
return "parallelogram";
}
else{
System.out.print("quadrilateral");
return "quadrilateral";
}
}

Java Access Modifier Best Practice

This may seem a basic question, but I'd like to get this right.
I have a Class 'AWorld'. Within that class, I have a method that draws a border, depending on the map size set by the user.
If the variable 'mapSize' is private, but I want to access it's value from within the same class, is it more appropriate to reference it directly, or use a getter method.
The code below should explain what I'm wanting to know.
package javaFX;
public class AWorld {
//initialized later
AWorld newWorld;
private int mapSize = 20;
public int getMapSize()
{
return mapSize;
}
public void someMethod()
{
int var = newWorld.mapSize; //Do I reference 'mapSize' using this...
}
// Or...
public void someOtherMethod()
{
int var = newWorld.getMapSize(); //Or this?
}
public static void main(String[] args) {}
}
Either of those is ok since you're getting a primitive field. If the get method does another operation before returning the data e.g. performing a math operation on the value, then it would be better to use it rather than calling the field directly. This is specially meant when using proxy/decorator pattern on your classes.
Here's an example of the second statement from above:
//base class to be decorated
abstract class Foo {
private int x;
protected Foo foo;
public int getX() { return this.x; }
public void setX(int x) { this.x = x; }
public Foo getFoo() { return this.foo; }
//method to prove the difference between using getter and simple value
public final void printInternalX() {
if (foo != null) {
System.out.println(foo.x);
System.out.println(foo.getX());
}
}
}
//specific class implementation to be decorated
class Bar extends Foo {
#Override
public int getX() {
return super.getX() * 10;
}
}
//decorator
class Baz extends Foo {
public Baz(Foo foo) {
this.foo = foo;
}
}
public class Main {
public static void main(String[] args) {
Foo foo1 = new Bar();
foo1.setX(10);
Foo foo2 = new Bar(foo1);
//here you see the difference
foo2.printInternalX();
}
}
Output:
10
100
You better dereference it directly.
The point of the private modifier is not to expose internal implementation to other classes. These other classes will use the getter method to get the value of the private property.
In your own class, there is no point on using the getter. Worse, someone may have overridden that method in a class that extends your class, and the getter may perform something that you do not expect
IMHO, if you are referencing a field of the current instance the general rule is to access the field directly with mapSize or this.mapSize.
If you are referencing a value from a different instance (be it of the same class or a different class, I would use the getter method). I believe this would lead to simpler refactoring. It also maintains the contract that any other instance gets the field value via the getter which allows for additional functionality in the getter.

Java Classloading and Reflection

I am loading a jar file at runtime using urlclassloader.
Jar file and the classes are getting successfully loaded.
I have a class with a method that return an Object X.
Using the object X, i have to call Setter methods on the X.
How do I call the setter methods on the X?
I have the object X returned by invoking the method.
X = my.invoke(inst, obj);
Do I need to create an instance again by calling newInstance() method on X class?
To call the methods of Object X, do I have to call method.invoke() each and every time ?
Assume X object has 5 methods, find the method and invoke the method using Method.invoke.
Your suggestions will be really helpful.
File f1 = new File("/home/egkadas/CR364/lib/xxx.jar");
URL urls [] = new URL[1];
urls[0] = f1.toURL();
URLClassLoader urlClass = URLClassLoader.newInstance(urls);
Class c1 = urlClass.loadClass("com.xxxx.example.poc.Container");
Container inst = (Container)c1.newInstance();
if(inst == null){
System.out.println("Object is null");
}else{
Method my = c1.getMethod("getAttribute",null);
Object[] obj = new Object[0];
com.XXXXX.example.poc.Container.Attributes att =(com.XXXXX.example.poc.Container.Attributes)my.invoke(inst, obj);
System.out.println(att);
Code in the jar :
public class Container {
public String id;
public Container(){
}
public Container(String id){
this.id=id;
}
public void setId(String id){
this.id=id;
}
public Attributes getAttribute(){
return new Attributes("check","12lb","15lb",100);
}
public List<Attributes> getAttributes(){
List<Attributes> ats = new ArrayList<Attributes>();
return ats;
}
public static class Attributes {
public String name;
public String weight;
public String height;
public int capacity;
public Attributes(String name,String weight,String height,int capacity){
this.name=name;
this.weight=weight;
this.height=height;
this.capacity=capacity;
}
public Attributes(){
}
public String toString(){
return this.name+" "+this.weight+" "+this.height+" "+this.capacity;
}
public void setName(String name){
this.name=name;
}
public void setWeight(String weight){
this.weight =weight;
}
public void setHeight(String height){
this.height=height;
}
public void setCapacity(int cap){
this.capacity=cap;
}
}
}
Do I need to create an instance again by calling newInstance() method on X class?
No, given your explanations, you already have an object X. You don't need to create a new one of whatever type it is.
To call the methods of Object X, Do i have to call method.invoke()
each and every time ? Assume X object has 5 methods, find the method
and invoke the method using Method.invoke.
Reflection is a run time thing. You don't know the declared (or static) types to work with. You're basically only working with the Object interface/contract. As such, you need to do everything through the reflection utilities. If you want to call a method of an object, you need to retrieve the corresponding Method object and call its invoke(..) method with the correct arguments.
That depends on which classloader defines the X class. If it is the parent classloader, you can simply cast your return value:
X x = (X) my.invoke(inst, obj);
and then use it like any other java object.
If X is defined by your custom classloader, it gets more complicated, as the definition of X is not visible to classes loaded by the parent class loader. Therefore, these classes can not refer to the methods and fields of X in their source code. The usual workaround is to have an interface (let's call it Y) in the parent class loader that is implemented by X in the custom class loader. Since the methods are declared in Y, they are accessible from the parent class loader, even if calling them executes the implementation in class X.
If you can't do that either, you can still invoke these methods using reflection.

Categories