I have an assignment from my Java 1 class (I'm a beginner) and the question instructs us to make some code more object-oriented. I've done what I can for the assignment, but one of my files consistently gives me a Cannot Find Symbol Method error even though the files are in the same project. I know the methods are there, so what's going on? The error only occurs in AlienPack, which doesn't seem to recognize the other files, all of which are in the same project (including AlienPack). The getDamage() method that's being called in AlienPack isn't being found (it's in SnakeAlien, OgreAlien, etc).
EDIT: The new error for the getDamage() methods I'm trying to invoke in AlienPack is that the methods still aren't being found. AlienDriver can't find calculateDamage() either.
Here's the code I've got so far:
Alien:
public class Alien {
// instance variables
private String name;
private int health;
// setters
public void setName(String n) {
name = n; }
public void setHealth(int h) {
if(h>0&&h<=100) {
health = h;
} else {
System.out.println("Error! Invalid health value!");
System.exit(0); } }
// getters
public String getName() {
return name; }
public int getHealth() {
return health; }
// constructors
public Alien() {
setName("No name");
setHealth(100); }
public Alien(String n, int h) {
setName(n);
setHealth(h); }
public Alien(Alien anAlien) {
setName(anAlien.getName());
setHealth(anAlien.getHealth()); }
public Alien clone() {
return new Alien(this);
} }
SnakeAlien:
public class SnakeAlien extends Alien { // new file
// instance variables
private int damage;
// setters
public void setDamage(int d) {
if(d>0) {
damage = d;
} else {
System.out.println("Error! Invalid damage value!");
System.exit(0); } }
// getters
public int getDamage() {
return damage; }
// constructors
public SnakeAlien() {
super();
setDamage(0); }
public SnakeAlien(String n, int h, int d) {
super(n, h);
setDamage(d); }
public SnakeAlien(SnakeAlien anAlien) {
super(anAlien);
setDamage(anAlien.getDamage()); }
public SnakeAlien clone() {
return new SnakeAlien(this);
} }
OgreAlien:
public class OgreAlien extends Alien { // new file
// instance variables
private int damage;
// setters
public void setDamage(int d) {
if(d>0) {
damage = d;
} else {
System.out.println("Error! Invalid damage value!");
System.exit(0); } }
// getters
public int getDamage() {
return damage; }
// constructors
public OgreAlien() {
super();
setDamage(0); }
public OgreAlien(String n, int h, int d) {
super(n, h);
setDamage(d); }
public OgreAlien(OgreAlien anAlien) {
super(anAlien);
setDamage(anAlien.getDamage()); }
public OgreAlien clone() {
return new OgreAlien(this);
} }
MarshmallwManAlien:
public class MarshmallowManAlien extends Alien { // new file
// instance variables
private int damage;
// setters
public void setDamage(int d) {
if(d>0) {
damage = d;
} else {
System.out.println("Error! Invalid damage value!");
System.exit(0); } }
// getters
public int getDamage() {
return damage; }
// constructors
public MarshmallowManAlien() {
super();
setDamage(0); }
public MarshmallowManAlien(String n, int h, int d) {
super(n, h);
setDamage(d); }
public MarshmallowManAlien(MarshmallowManAlien anAlien) {
super(anAlien);
setDamage(anAlien.getDamage()); }
public MarshmallowManAlien clone() {
return new MarshmallowManAlien(this);
} }
AlienPack:
public class AlienPack { // new file, this one isn't recognizing the others
// instance variables
private Alien[] pack;
// setters
public void setPack(Alien[] aliens) {
pack = new Alien[aliens.length];
for(int i = 0; i<aliens.length; i++) {
pack[i]=aliens[i].clone(); } }
// getters
public Alien[] getPack() {
Alien[] temp = new Alien[pack.length];
for(int i = 0; i<pack.length; i++) {
temp[i]=pack[i].clone(); }
return temp; }
// constructors
public AlienPack() {
Alien[] nothing = new Alien[1];
nothing[0]=null;
setPack(nothing); }
public AlienPack(Alien[] aliens) {
setPack(aliens);}
// other methods
public int calculateDamage() {
int damage = 0;
for(int i = 0; i<pack.length; i++) {
if((new SnakeAlien()).getClass()==pack[i].getClass()) {
pack[i].getDamage() +=damage;
} else if((new OgreAlien()).getClass()==pack[i].getClass()) {
pack[i].getDamage() +=damage;
} else if((new MarshmallowManAlien()).getClass()==pack[i].getClass()) {
pack[i].getDamage() +=damage;
} else {
System.out.println("Error! Invalid object!");
System.exit(0); } }
return damage; } }
AlienDriver:
public class AlienDriver { // driver class
public static void main(String[] args) {
Alien[] group = new Alien[5];
group[0]= new SnakeAlien("Bobby", 100, 10);
group[1]= new OgreAlien("Timmy", 100, 6);
group[2]= new MarshmallowManAlien("Tommy", 100, 1);
group[3]= new OgreAlien("Ricky", 100, 6);
group[4]= new SnakeAlien("Mike", 100, 10);
System.out.println(group.calculateDamage());
} }
Two problems:
pack[i].getClass().getDamage() ...
should be just
pack[i].getDamage() ...
You seem to be confused about what the getClass() method does. It returns an object which represents the class (i.e. java.lang.Class) of another object. It is used for reflection. To invoke getDamage() you would just invoke it directly on pack[i] as shown above.
However...
You are attempting to invoke the method getDamage() using a reference of type Alien, which is a base class of all the concrete alien types. If you want to do it that way,
getDamage() needs to be declared abstract in the base class so it can be found and dispatched to the correct subclass when invoking it via an Alien reference.
In Alien:
public abstract class Alien {
...
public abstract int getDamage();
An alternative is to cast to the appropriate subclass at each point since you know what it is:
((SnakeAlien)pack[i]).getDamage() +=damage;
However (again) even that is wrong. You can't apply += to an "rvalue". What you need to do here is either:
Also declare setDamage() abstract in Alien and do pack[i].setDamage(pack[i].getDamage()+damage);
If casting, ((SnakeAlien)pack[i]).setDamage( ((SnakeAlien)pack[i].getDamage()) + damage);
My Recommendation:
In class Alien:
public abstract class Alien {
...
private int damage = 0; // Move damage up to the abstract base class
public int addToDamage(int n) { this.damage += n; }
...
}
In your driver, no need to test the class. Invoke the addToDamage() method on the Alien reference.
I think that at least part of your problem is the getClass() method. You are expecting it to return an object but it does not. Just call directly to the array.
pack[I].getDamage()
should work assuming that the correct type of object is stored in pack()
Related
Why is the reference variable ‚Input inside‘ necessary?
How does the ‚Input inside‘ work here?
What does the code: The code adds 5 to the x-value (in this case 4) and uses the square of the new value. So (4+5)^2.
Thank you. 😀
Code:
abstract class Input {
protected Input inside;
public Input() {
}
public Input(Input inside) {
this.inside = inside;
}
public int calculate(int value) {
if(inside == null) {
return value;
}
return inside.calculate(value);
}
public static void main(String[] args) {
Input chaincalculate = new Square(new AddFive());
int x;
x = 4;
System.out.println("The value is: " + (int) chaincalculate.calculate(x));
}
}
class AddFive extends Input {
public AddFive() {
}
public AddFive(Input inside) {
super(inside);
}
public int calculate(int value) {
value = super.calculate(value);
return value+5;
}
}
class Square extends Input {
public Square() {
}
public Square(Input inside) {
super(inside);
}
public int calculate(int value) {
value = super.calculate(value);
return value * value;
}
}
}
All the classes extending the abstract class Input, have their own calculate methods, and since, these classes, would want to use the abstract class Calculate method, the reference variable input inside is necessary to invoke/reference the calculate method residing in Input abstract class, to support the method chaining implemented in the code
Im trying to create a subclass object using an enum from the super class but when I try to create the object in the subclass I get this error.
error: constructor Payroll in class Payroll cannot be applied to given types;
public PayClaim(int hours, PayLevel level){
^
required: PayLevel
found: no arguments
reason: actual and formal argument lists differ in length
1 error
This is my superclass Payroll
public class Payroll{
static double OVERTIME_RATE = 1.5;
static int REGULAR_WEEK = 40;
static int LEVEL_ONE_PAY = 15;
static int LEVEL_TWO_PAY = 25;
static int LEVEL_THREE_PAY = 40;
public enum PayLevel{
ONE, TWO, THREE
}
private PayLevel levels;
public Payroll(PayLevel levels){
this.levels = levels;
}
public PayLevel getPayLevel(){
return levels;
}
public static void main (String [] args) {
Payroll.OVERTIME_RATE = 1.75;
Payroll.REGULAR_WEEK = 40;
Payroll.LEVEL_ONE_PAY = 12;
System.out.println(Payroll.calculatePay(35, Payroll.PayLevel.ONE));
}
public static double calculatePay(int noHoursWorked, PayLevel level){
//do stuff
}
}
And this is my subclass PayClaim
public class PayClaim extends Payroll{
int noHoursWorked;
public Payroll.PayLevel payLevel;
double calculatedPay = 0;
public static void main (String [] args) {
PayClaim p = new PayClaim(1, Payroll.PayLevel.ONE);
System.out.println(p);
}
public PayClaim(int hours, PayLevel level){
if(hours > 80 || hours < 1){
throw new IllegalArgumentException();
}
else{
noHoursWorked = hours;
payLevel = level;
}
}
public int getNoHoursWorked(){
return noHoursWorked;
}
public PayLevel getPayLevel(){
return payLevel;
}
public double getClaculatedPay(){
return calculatedPay;
}
public void setCalculatedPay(double pay){
//
}
public String toString(){
//
}
My apologies if I missed something trivial its just that the code wont even compile so I'm really struggling to find just where I'm going wrong here.
I believe the answer you are looking for is very simple. If you invoke the parent constructor to the subclass, this should resolve the compilation problems. You can do this by using the following changes. The change I made is at the beginning of the constructor, it simply calls the parents constructor to create an object, since it is a subclass.
public class PayClaim extends Payroll{
int noHoursWorked;
public Payroll.PayLevel payLevel;
double calculatedPay = 0;
public static void main (String [] args) {
PayClaim p = new PayClaim(1, Payroll.PayLevel.ONE);
System.out.println(p);
}
public PayClaim(int hours, PayLevel level){
enter code here
super(level);
if(hours > 80 || hours < 1){
throw new IllegalArgumentException();
}
else{
noHoursWorked = hours;
payLevel = level;
}
}
public int getNoHoursWorked(){
return noHoursWorked;
}
public PayLevel getPayLevel(){
return payLevel;
}
public double getClaculatedPay(){
return calculatedPay;
}
public void setCalculatedPay(double pay){
//
}
public String toString(){
//
}
I have a class called classes who has this compareto method:
#Override
public int compareTo(Object other) {
Cours ot = (Cours)other;
String heure2 = ot.heure;
int autre = Integer.parseInt(heure2.substring(0,2));
int le = Integer.parseInt(this.heure.substring(0,2));
if (autre > le) {
return 1;
}
if (autre == le) {
return 0;
} else {
return -1;
}
}
I have another class called day that has a list of classes :
private List<Cours> journee;
And a method to sort the classes:
public void TrieListe() {
Collections.sort(journee);
}
When I use TrieListe() everything works fine, I can sort the list.
But I've added another class called Weeks which contains a List of Days
And now I want to use TrieList() from that class :
private List<Days> leWeek;
public void TrieListe() {
Collections.sort(leWeek);
}
So how can I use my compareTo method from my classes class using sort() in my Weeks class.
Create a new abstract class AComparableByHour and make your classes extend it.
public abstract class AComparableByHour implements Comparable<AComparableByHour> {
public abstract String getHeure();
// Your comparison method goes here
#Override
public int compareTo(AComparableByHour ot) {
String heure2 = ot.getHeure();
int autre = Integer.parseInt(heure2.substring(0,2));
int le = Integer.parseInt(this.getHeure().substring(0,2));
if( autre > le){
return 1;
}
if( autre == le){
return 0;
} else {
return -1;
}
}
}
public class Cours extends AComparableByHour {
// This method is mandatory now.
// You could move it to the new superclass
public String getHeure() {
return heure;
}
...
}
public class Days extends AComparableByHour {
public String getHeure() {
return heure;
}
...
}
I have a class called classes who has this compareto method:
#Override
public int compareTo(Object other) {
This is already wrong. Your class should implement Comparable<classes> (noting that classes is a truly terrible name for a class, for at least three separate reasons), which will force the method signature to be:
#Override
public int compareTo(classes other) {
Good Day,
I am writing a custom event handler in Java. I have a class called BoogieCarMain.java that instantiates three instances of a type called BoogieCar. Whenever any of the three instances exceeds a certain speed limit, then an event should be fired off. The code I currently have is working, so here is what I have:
// BoogieCar.java
import java.util.ArrayList;
public class BoogieCar {
private boolean isSpeeding = false;
private int maxSpeed;
private int currentSpeed;
private String color;
BoogieSpeedListener defaultListener;
public BoogieCar(int max, int cur, String color) {
this.maxSpeed = max;
this.currentSpeed = cur;
this.color = color;
}
public synchronized void addSpeedListener(BoogieSpeedListener listener) {
defaultListener = listener;
}
public void speedUp(int increment) {
currentSpeed += increment;
if (currentSpeed > maxSpeed) {
processSpeedEvent(new BoogieSpeedEvent(maxSpeed, currentSpeed, color));
isSpeeding = true;
} else {
isSpeeding = false;
}
}
public boolean getSpeedingStatus() {
return isSpeeding;
}
private void processSpeedEvent(BoogieSpeedEvent speedEvent) {
defaultListener.speedExceeded(speedEvent);
}
}
// BoogieCarMain.java
import java.util.ArrayList;
public class BoogieCarMain {
public static void main(String[] args) {
BoogieCar myCar = new BoogieCar(60, 50, "green");
BoogieCar myCar2 = new BoogieCar(75, 60, "blue");
BoogieCar myCar3 = new BoogieCar(65, 25, "pink");
BoogieSpeedListener listener = new MySpeedListener();
myCar.addSpeedListener(listener);
myCar2.addSpeedListener(listener);
myCar3.addSpeedListener(listener);
myCar.speedUp(50); // fires SpeedEvent
System.out.println(myCar.getSpeedingStatus());
myCar2.speedUp(20);
System.out.println(myCar2.getSpeedingStatus());
myCar3.speedUp(39);
System.out.println(myCar3.getSpeedingStatus());
}
}
// BoogieSpeedListener.java
public interface BoogieSpeedListener { // extends java.util.EventListener
public void speedExceeded(BoogieSpeedEvent e);
}
// MySpeedListener.java
public class MySpeedListener implements BoogieSpeedListener {
#Override
public void speedExceeded(BoogieSpeedEvent e) {
if (e.getCurrentSpeed() > e.getMaxSpeed()) {
System.out.println("Alert! The " + e.getColor() + " car exceeded the max speed: " + e.getMaxSpeed() + " MPH.");
}
}
}
// BoogieSpeedEvent.java
public class BoogieSpeedEvent { // extends java.util.EventObject
private int maxSpeed;
private int currentSpeed;
private String color;
public BoogieSpeedEvent(int maxSpeed, int currentSpeed, String color) {
// public SpeedEvent(Object source, int maxSpeed, int minSpeed, int currentSpeed) {
// super(source);
this.maxSpeed = maxSpeed;
this.currentSpeed = currentSpeed;
this.color = color;
}
public int getMaxSpeed() {
return maxSpeed;
}
public int getCurrentSpeed() {
return currentSpeed;
}
public String getColor() {
return color;
}
}
My question is: While this code works, I would like the BoogieCar type to notify BoogieCarMain directly without me have to "poll" the BoogieCar type by having to invoke the getSpeedingStatus() method.
In other words, perhaps defining a variable in BoogieCarMain.java that changes whenever one of the three cars exceeds its predefined speed limit. Is it possible to have the BoogieCar type set the variable?
Is there a cleaner way to do this?
TIA,
coson
Callbacks are ideal for this scenario.
// BoogieCarMain provides a sink for event-related information
public void handleSpeeding(BoogieCar car) {
System.out.println(car.getSpeedingStatus());
}
// MySpeedListener knows about an object that wants event-related information.
// I've used the constructor but an addEventSink method or similar is probably better.
public MySpeedListener(BoogieCarMain eventSink) {
this.eventSink = eventSink;
}
// MySpeedListener handles events, including informing objects that want related information.
// You decide if the event is an appropriate type for the sink to know about.
// Often it isn't, and instead your listener should pull the relevant info out of the event and pass it to the sink.
public void speedExceeded(BoogieSpeedEvent e) {
if (e.getCurrentSpeed() > e.getMaxSpeed()) {
// I've taken the liberty of adding the event source as a member of the event.
eventSink.handleSpeeding(e.getCar());
}
}
I'm experimenting with ways of creating immutable objects. The following builder objects
are quite attractive because they keep the role of the arguments clear. However I would like
to use the compiler to verify that certain fields are set, like with the Immutable() constructor invocation. StrictImmutableBuilder provides those checks, but is rather noisy. Is there some way to get the same checks but with the form of LaxImmutableBuilder? Perhaps using annotations?
public class Immutable {
public static void main(String[] args) {
new Immutable("13272873C", 23, false);
// nice but what where those arguments?
new LaxImmutableBuilder() {{
refCode("13272873C");
age(23);
subscribed(false);
}}.build();
// now I know what each value represents
// but what if I forgot to set one?
new StrictImmutableBuilder() {
public String refCode() { return "13272873C"; }
public int age() { return 23; }
public boolean subscribed() { return false; }
}.build();
// now I'm forced to set each field, but now
// we have the extra noise of "return"
// and also "public" if we want to use
// this outside the current package
// is there another way? maybe using annotations?
}
private final String refCode;
private final int age;
private final boolean subscribed;
public String getRefCode() {
return refCode;
}
public int getAge() {
return age;
}
public boolean isSubscribed() {
return subscribed;
}
public Immutable(String a, int b, boolean c) {
this.refCode = a;
this.age = b;
this.subscribed = c;
}
}
abstract class StrictImmutableBuilder {
public abstract String refCode();
public abstract int age();
public abstract boolean subscribed();
public Immutable build() {
return new Immutable(refCode(), age(), subscribed());
}
}
abstract class LaxImmutableBuilder {
private String refCode;
private int age;
private boolean subscribed;
protected void refCode(String refCode) {
this.refCode = refCode;
}
protected void age(int age) {
this.age = age;
}
protected void subscribed(boolean subscribed) {
this.subscribed = subscribed;
}
public Immutable build() {
return new Immutable(refCode, age, subscribed);
}
}
Here's the pattern I use:
class YourClass {
// these are final
private final int x;
private final int y;
private int a;
private int b;
// finals are passed into the constructor
private YourClass(int x, int y) {
this.x = x;
this.y = y;
}
public static class Builder {
// int x, int y, int a, int b
// whatever's final is passed into constructor
public Builder(int x, int y) {
this.x = x;
this.y = y;
}
// a and b are optional, so have with() methods for these
public Builder withA(int a) {
this.a = a;
return this;
}
public Builder withB(int b) {
this.b = b;
return this;
}
public YourClass build() {
YourClass c = new YourClass (x, y);
c.a = a;
c.b = b;
return c;
}
}
}
there is this trick: Type-safe Builder Pattern
http://michid.wordpress.com/2008/08/13/type-safe-builder-pattern-in-java/
but that's just too crazy.