Say I have a method in a class that carries out movement (call it move(Earth)). The function is implemented in another class using inheritance and such like this:
animal.move(Earth)
Is it possible to randomize the actual implementation without messing with the function method?
public void rMove(Earth myEarth) throws InterruptedException
{
int x = (int) location.getX();
int y = (int) location.getY();
int xMax = myEarth.getX() - 1;
int yMax = myEarth.getY() - 1;
double w = Math.random();
int rMove = (int) (w + Math.random()*4);
switch(rMove)
{
case NOR:
location.setLocation(x,y-1);
break;
case SOU:
location.setLocation(x,y+1);
break;
case EAS:
location.setLocation(x+1,y);
break;
case WES:
location.setLocation(x-1,y);
break;
}
}
The class containing this method is extended into another class
public class Carnivore extends Animal
Within the class carnivore, the animal moves using the above function like this:
super.rMove(myEarth);
There's a whole bunch of other code involving the movement but I don't think it's relevant. My question is how to modify the above implementation without modifying the actual rMove.
I would look at having a separate method for the randomisation logic that can be overridden by the subclasses of Animal. I'm not a Java developer so the syntax might not be completely correct, but this gives you an idea. For example:
public abstract class Animal
{
public abstract int moveRandom();
}
public class Carnivore extends Animal
{
public int moveRandom() {
double w = Math.random();
int rMove = (int) (w + Math.random()*4);
return rMove;
}
}
public void rMove() {
int rMove = this.rMove();
}
Related
I'm learning Lambda expressions and method references in Java 8 and see that we can refer to the super-class version of a method by use of 'super', as:
super::name
But when I do this, it is not working. Here is the sample code:
interface MyInterface {
int someFunc(int x);
}
class A {
static int Func(int y) {
// return (int) (Math.random() * y);
return y;
}
}
class B extends A {
static int Func(int y) {
// return (int) (Math.random() * y);
return y + 1;
}
}
public class Test {
public static void main(String[] args) {
System.out.print("Enter a number: ");
java.util.Scanner scanner = new java.util.Scanner(System.in);
int result = funcOp(B::Func, scanner.nextInt()); // <-This works.
//int result = funcOp(B.super::Func, scanner.nextInt()); <--This is not working.
//Getting: error: not an enclosing class: B
int result = funcOp(B.super::Func, scanner.nextInt());
^
scanner.close();
System.out.println(result);
}
static int funcOp(MyInterface mI, int num) {
return mI.someFunc(num);
}
}
Please tell me, am I implementing this code wrong? From what I understood, we can pass a method "X" as reference in place where implementation for method "Y" of a functional interface is expected since method "X" satisfies the conditions and behavior of method "Y" and could potentially replace method "Y" in that situation.
Is this not right,did I get methods references in the wrong way?
Thanks for your inputs on this :)
From the JLS:
The form super.Identifier refers to the field named Identifier of the current object, but with the current object viewed as an instance of the superclass of the current class.
[...]
The forms using the keyword super are valid only in an instance method, instance initializer, or constructor of a class, or in the initializer of an instance variable of a class. If they appear anywhere else, a compile-time error occurs.
You are calling super from a class type, thus the compilation error.
As many suggest in the comment you should just pass A::Func in the funcOp method.
Note that you won't be able to call super from your Func method either, as it's a static method, so it's not tied to a class instance.
Edit following OP's comment
You can use the super keyword from an instance method (so, if you remove static) and it'd look like this:
class B extends A {
int Func(int y) {
// e.g:
if (y > 10) {
return super.Func(y); // call Func from the parent class
}
return y + 1;
}
}
super and this keywords are reference variable that refers to some object. In other words it belongs to instance of the class.
You can do something like this if your looking for alternate approach rather than A::Func
class B extends A {
static int Func(int y) {
// return (int) (Math.random() * y);
return y + 1;
}
public int getSuperFunc(int y)
{
//call A class Func(int y)
return super.Func(y);
}
}
And in Test class main method
System.out.print("Enter a number: ");
java.util.Scanner scanner = new java.util.Scanner(System.in);
//int result = funcOp(B::Func, scanner.nextInt()); // <-This works.
B b=new B();
int result1 = funcOp(b::getSuperFunc, scanner.nextInt()); // <-This works.
scanner.close();
System.out.println(result1);
Output
Enter a number: 1
1
I have test case that does something like this
TestSquare.java
public void testEncaps() {
Shifting shift = new Shifting(150,260);
Square s = new Square(new Point(101,201),130,140,shift);
Point p = s.getMidPoint();
p.x = 215;
p.y = 315;
assertEquals(new Point(101,201),s.getMidPoint());
}
So on the last line, the s.getMidPoint() don't equal to the Point(101, 201) but instead gets overridden with 215,315. Here is my constructor code and get method.
Square.java
public Square(Point newP, int width, int height, Shift newS) {
this.newMidPoint = newP;
this.newWidth = width;
this.newHeight = height;
this.newShift= newS;
}
public Point getMidPoint() {
return newMidPoint;
}
So, s.getMidPoint() shouldn't be replaced with the Point object. What am I doing wrong?
This two codes are in different class. So there is no main method in Square.java
If you don't want another class to be able to edit Square's middle, return a new Point:
public Point getMidPoint() {
return new Point(newMidPoint);
}
Then your test will run green.
while trying to get a grasp of polymorphism and inheritance, I made a small program to demonstrate these topics. The program consists of a superclass 'Tree' and three subclasses 'Birch', 'Maple', and 'Oak'. Tree's constructor makes it so that all trees start off with a height of 20 and 200 leaves. In Tree I have an abstract method called grow().
Here's the code for Tree:
public abstract class Tree {
private int height;
private int numberOfLeaves;
public Tree()
{
height = 20;
numberOfLeaves = 200;
}
public Tree(int aheight, int anum)
{
height = aheight;
numberOfLeaves = anum;
}
public int getHeight()
{
return height;
}
public int getNumberOfLeaves()
{
return numberOfLeaves;
}
public void setNumberOfLeaves(int anum)
{
numberOfLeaves = anum;
}
public abstract String getType();
public void setHeight(int aheight)
{
height = aheight;
}
public abstract void grow();
}
Here's the code in Birch for grow().
public void grow()
{
int height = super.getHeight();
super.setHeight(height++);
int num = super.getNumberOfLeaves();
super.setNumberOfLeaves(num+=30);
System.out.println("The Birch is Growing...");
}
However, when I call code to make an array of trees grow, none of their heights or number of leaves change.
Here's the code I used to populate the array of trees (I did it manually):
ArrayList<Tree> treeArray = new ArrayList<Tree>();
treeArray.add( new Oak());
treeArray.add(new Birch());
treeArray.add(new Maple());
And Here's the code I used to call grow:
for (Tree tree : treeArray)
{
tree.grow();
System.out.println("The " + tree.getType() + "'s height is " + tree.getHeight() + " and it's number of leaves is "+ tree.getNumberOfLeaves() +".");
}
Clearly, the values in the superclass aren't being modified. Any help will be appreciated! Thanks!
Change your code to :
int height = super.getHeight();
super.setHeight(++height);
note that you don't need to call super.method(). as long as the method is protected (public even better) you can just simplify it to :
int height = getHeight();
setHeight(++height);
You only call super. if you implement the method again in your child class and want to specifically call the parent class, which usually can be seen in constructor calling parent constructor.
One more thing : your accessor need to be changed a bit just for pre-caution case. see code below. Usually your IDE should support auto generation of accessor.
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
This code:
int height = super.getHeight();
super.setHeight(height++);
isn't going to change anything, because the increment of height will occur after the call to super.setHeight(). So you're just setting the height to its current value.
I have a problem
I have some classes of objects, they are called "cat" "dog" etc..
Within these classes I have assigned each cat and dog object their own integer energy level (so when they "move" through a 2dimensional array they loose and gain energy).
I reference it by saying this.energylevel.
Because "energylevel" it is specific to each object I cannot make it static.
how can I let the "dog class" see the energy level of the cat objects that is stored non statically within the "cat class"?
and I cannot instantiate Cat c = new Cat(); within the dog class it is already done within the main method.
This is all part of a massive project so forgive me if I have not explained it clearly enough
You can add a static method inside the Cat object that will return the non-static variable based on the Cat's ID. You'll need to keep a list of Cats in a static map inside the Cat object.
private static HashMap<String,Cat> cats = new HashMap<String,Cat>();
...
public static int getEnergy(String catId) {
Cat myCat = cats.get(catId);
return myCat.getEnergy();
}
public int getEnergy() {
return this.energy()
}
Alternatively as requested, if you want to search by X,Y:
private static ArrayList<Cat> cats = new ArrayList<Cat>();
private int energy = 100;
private int x = 0;
private int y = 0;
...
public static int getEnergy(int x, int y) {
//Energy of -1 being the error (not found) state.
int energy = -1;
for(Cat cat : cats) {
if(cat.getX() == x && cat.getY() == y) {
energy = cat.getEnergy();
}
}
return energy;
}
public int getEnergy() {
return this.energy()
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
I'm working through an exercise sheet regarding interfaces, generics and abstract classes in Java. No matter what way I seem to code it, the class Exercise1 won't work. The question asked are commented in the code. Any help would be appreciated, I'm not sure if the error is in the Exercise one code or the implementation of the interface in the classes Time and Point.
/*Exercise 2
(a) Write an interface Printable which has a single method put whose intention is to display a string representation of any object whose class implements Printable. Check it by compiling it. */
interface Printable {
public void put(Object o);
}
/*(b) Enhance classes Point and Time from Chapter 2 of the notes to implement Printable. Check them by compiling them. */
class Point implements Printable {
static Scanner sc = new Scanner(System.in);
private double x, y; // coordinates
Point(double x, double y){ // all-args constructor
this.x = x; this.y = y;
}
Point(){}; // no-args constructor (defaults apply)
void get() {
x = sc.nextDouble();
y = sc.nextDouble();
}
public String toString() {
return "(" + x + "," + y + ")";
}
double distance(Point r) { // distance from r
double xdist = x-r.x; double ydist = y-r.y;
return(Math.sqrt(xdist*xdist+ydist*ydist));
}
public void put(Object o) {
if(o==null) return;
Point p = (Point)o;
System.out.println(x + ":" + y);
}
}
class Time implements Order, Printable {
private int hours; // 0..23
private int mins; // 0..59
Time() { }
Time (int hours, int mins) {
this.hours = hours;
this.mins = mins;
}
public boolean lte(Object other) { // Note public
if (other==null) return false;
Time t = (Time) other;
return hours*60+mins<=t.hours*60+t.mins;
}
public void put(Object o) {
if(o==null) return;
Time t = (Time)o;
System.out.printf("%02d:%02d\n", t.hours, t.mins);
}
}
/*(c) Write a static method print which takes an array of objects whose class implements Printable, and prints each element in the array, one element per line. Check it by placing it in an otherwise empty class and compiling it. */
//this is the bit that is giving me grief, I've tried :
public class Exercise1 {
static void print(Printable[] a) {
for(int i = 0; i < a.length ; i++) {
a[i].put(); // put(java.lang.Object) in Printable cannot be applied to () //a[i].put();
}
}
public static void main(String[] args) {
Time[] t = new Time[10];
for(int i = 0; i < t.length; i++) {
t[i] = new Time();
}
print(t);
}
}
public interface Order {
boolean lte (Object obj); // Object for max generality
// is this object less than or equal to obj?
}
You want to print this, not some arbitrary object o.
I think the problem is the interface Printable. It doesn't match the question correctly.
to display a string representation of any object whose class implements Printable
This doesn't mean, that the put() method should have a parameter of type Object.
The object here refers to this, the object which class implements Printable. And the method put() should print out a string representation of this. So in the simplest case you can implement it with the help of toString().
interface Printable {
/**
* Display a string representation of this
*/
void put();
}
class Point implements Printable {
// ...
/**
* returns a string representation of this
*/
public String toString() {
return "(" + x + "," + y + ")";
}
public void put() {
// this is the same as System.out.println(this.toString());
System.out.println(this);
}
}
Then you can call put() for every Printable in your array.
What you want to do is make the interface Printable look something like this:
interface Printable {
public void print(); //The name of the method should be similar to the name of the interface
}
Then your classes will work like this:
public class Time implements Printable {
private int hours, minutes;
public void print() {
System.out.println( hours + ":" + minutes );
}
}
For Exercise 1, you would then call print() for each element of the array.
By the way: There's already an interface similar to Order. It's called Comparable, and it looks like this:
public interface Comparable<T> {
public void compareTo(T other); //Returns -1 if less than, 0 if equal, and 1 if greater than other object.
}
If no parameter T is given, it becomes Object.
you might want your Printable method to be print(Object object), not put.