I want to, within my abstract class, define two constructors.
When create a new instance of the class, i want the toString to return something different depending on what was called:
The FireEngine Class
public class FireEngine extends EmergencyVehicle {
private String colour;
public FireEngine(String colour) {
super (colour);
}
public FireEngine() {
this("red");
}
public String toString () {
if (colour == "red") {
return "red";
} else
return "no";
}
}
The EmergencyVehicle class:
public abstract class EmergencyVehicle extends RoadVehicle {
public boolean codeBlue = false;
public EmergencyVehicle(String colour){
super(colour);
}
public boolean isEmergency () {
if (codeBlue == true) {
return true;
} else {
return false;
}
}
public void setEmergency(boolean newEmergency) {
codeBlue = newEmergency;
}
}
This is a homework exercise so I don't want the answer per se, but does the above code make sense?
For example, if I add a new EmergencyVehicle, I want an if statement depending on what colour the vehicle I add is.
1st Remark
Don't call
this("red");
in the default constructor, do
colour = "red";
unless the EmergencyVehicle(String colour) RoadVehicle(String colour) constructor is doing something else.
2nd Remark
Don't compare using
if (colour == "red")
use
if ("red".equals(colour))
3rd Remark
The method
public String toString()
is supposed to return a string representation of the instance. You implementation only returns red or no which is not very informative. Use something like
return("FireEngine(colour=" + colour + ")");
Related
I created an abstract class Fruit, which overrides the equals() method. Then I created a subclass, Orange, which overrides the copy() and the equals() method. In my test file, TestFruit.java, I am creating an array of oranges and testing their methods. I am trying to create a deep copy of orange and do a deep comparison between the parent orange and the copy. However, in my output, the comparison always returns false. I checked the parent and the copy's attributes and they do seem to be the same. Any pointers would be appreciated. I am pretty new to Java and copying. I attached my code below.
Fruit.java:
package juicer;
import copy.Copyable;
public abstract class Fruit implements Copyable, Cloneable
{
private double mass;
private boolean isJuicedRemoved;
protected Fruit(double theMass)
throws IllegalMassException
{
{
if (theMass <= 0)
{
throw new IllegalMassException(theMass);
}
else
{
this.mass = theMass;
this.isJuicedRemoved = false;
}
}
}
protected Fruit(Fruit fruit)
{
this.mass = fruit.mass;
this.isJuicedRemoved = fruit.isJuicedRemoved;
}
public double getMass()
{
return mass;
}
public boolean getIsJuicedExtracted()
{
return isJuicedRemoved;
}
protected void setMass(double value)
{
this.mass = value;
}
protected abstract double juiceRatio();
public double extractJuice()
{
double liquidMass = amountJuice();
if (!isJuicedRemoved)
{
isJuicedRemoved = true;
mass -= liquidMass;
}
return liquidMass;
}
public double amountJuice()
{
if (isJuicedRemoved) return 0.0;
return mass * juiceRatio();
}
#Override
public boolean equals(Object obj)
{
// Steps to override the equals() method():
// Step 1: Test if obj is an instance of Fruit.
// If it is not, then return false.
if (!(obj instanceof Fruit)) return false;
// Step 2: Cast obj to an Fruit.
Fruit rhs = (Fruit)obj;
// Step 3: Test if the data fields of the invoking object are
// equal to the ones in rhs using a deep comparison
// and return this result.
return super.equals(obj) && // test for equality in the super class
mass == rhs.mass &&
isJuicedRemoved == rhs.isJuicedRemoved;
}
#Override
public int hashCode()
{
int result = super.hashCode();
result = 31*result + Double.hashCode(mass);
result = 31*result + Boolean.hashCode(isJuicedRemoved);
return result;
}
#Override
public Object clone() throws CloneNotSupportedException
{
Fruit objectClone = (Fruit)super.clone();
objectClone.mass = mass;
objectClone.isJuicedRemoved = isJuicedRemoved;
return objectClone;
}
#Override
public String toString()
{
return "\tmass = " + mass +
"\n\tisJuiceExtracted = " + isJuicedRemoved + "\n";
}
}
Orange.java:
package juicer;
public class Orange extends Fruit
{
public Orange(double mass)
{
super(mass);
}
// copy constructor
public Orange(Orange other)
{
super(other);
}
#Override
protected double juiceRatio()
{
return 0.87;
}
#Override
public boolean equals(Object obj)
{
// Steps to override the equals() method():
// Step 1: Test if obj is an instance of Orange.
// If it is not, then return false.
if (!(obj instanceof Orange)) return false;
// Step 2: Cast obj to an Orange.
// This step is not needed since the only data fields this
// class has are the ones it inherits.
// Step 3: Test if the data fields of the invoking object are
// equal to the ones in rhs using a deep comparison
// and return this result.
return super.equals(obj);
}
#Override
public Object copy()
{
return new Orange(this);
}
#Override
public String toString()
{
return "Orange:\n" + super.toString();
}
}
TestFruit.java:
package test;
import juicer.*;
import java.util.Random;
public class TestFruit
{
public static void main(String[] args)
{
Orange[] oranges = new Orange[1];
//Random double generator for mass
Random rd = new Random();
//create oranges
for (int i = 0; i <= oranges.length - 1; i++ )
{
oranges[i] = new Orange(rd.nextDouble());
}
for (Orange orange : oranges)
{
Orange orangeCopy = new Orange(orange);
if (orange == orangeCopy)
{
System.out.print("The comparison is true!");
}
else
{
System.out.print("Does not match.");
}
}
}
}
One of the common misconceptions in Java is the use of == vs .equals(). When you use == to compare two objects in Java, internally it's comparing its memory address. == does not actually call .equals().
In this case, you have two distinct orange objects, so the comparison will always return false.
If you use a.equals(b), then it will actually invoke your equals method which you implemented.
As #Andreas pointed out in the comments, there's another issue. Calling super.equals(obj) in Fruit will call the superclass implementation of equals, and the superclass of Fruit is Object. Object.equals() behaves the same as == (i.e. also checking for reference equality). Overriding .equals() is not trivial, so it can often be nice to have the IDE generate it for you.
In contrast with a language like C++, Java does not have operator overloading. This means that you can't define a different implementation for ==. This is why it's best practice to always call .equals() when comparing any non-primitive types (unless you're explicitly checking reference equality, which is rare).
I am trying to increment the observations field in the Bird class. I have tried a few different ways, but I can't seem to get it to increment. Essentially, I want to call the addObservations() to add an observation to the count in the event the bird is already found in the Map. The issue clearly lies in the observe() in BirdData. Below is the code
public class Bird {
private String name;
private String latinName;
private int year;
private int observations;
public Bird (String name, String latinName, int year) {
this.name = name;
this.latinName = latinName;
this.year = year;
this.observations = 0;
}
public int getObservations() {
return this.observations;
}
public void addObservation() {
observations++;
}
public String getName() {
return this.name;
}
public String getLatinName() {
return this.latinName;
}
public int getYear() {
return this.year;
}
#Override
public boolean equals(Object o) {
if (o == null) {
return false;
} if (this.getClass() != o.getClass()) {
return false;
}
Bird compared = (Bird) o;
if (this.latinName == null || !this.latinName.equals(compared.latinName)){
return false;
} if (this.year != compared.year) {
return false;
}
return true;
}
#Override
public int hashCode() {
if (this.latinName == null) {
return 11;
}
return this.year +this.latinName.hashCode();
}
#Override
public String toString() {
return this.name + ", " +this.latinName + ": " + this.year + " " +this.observations;
}
}
public class BirdData {
private Map<Bird, String> birdList;
private Bird bird;
public BirdData() {
this.birdList = new HashMap<Bird, String>();
}
public void observe (Bird bird, String place) {
for (Bird b : birdList.keySet()) {
if (birdList.get(b).equals(bird)){
b.addObservation();
}
} if (!birdList.containsKey(bird)){
birdList.put(bird, place);
}
}
public void observations (Bird bird) {
if (birdList.containsKey(bird)) {
System.out.println(bird + " observations: " + bird.getObservations());
}
}
}
public class Main {
public static void main (String[] args) {
BirdData bl = new BirdData();
bl.observe(new Bird ("Rose Starling", "Sturnus roseus", 2012), "Arabia");
bl.observe(new Bird ("Rose Starling", "Sturnus roseus", 2012), "Arabia");
bl.observe(new Bird ("Rose Starling", "Sturnus roseus", 2012), "Arabia");
bl.observe(new Bird ("Rose Starling", "Sturnus roseus", 2018), "Arabia");
bl.observations(new Bird ("Rose Starling", "Sturnus roseus", 2012));
bl.observations(new Bird ("Rose Starling", "Sturnus roseus", 2018));
}
}
Replace the line
if (birdList.get(b).equals(bird)){
with
if (birdList.get(b).equals(place)){
Basically, you should add the bird to the observed list only if both the supplied parameters - bird and place are found in the map as a key value pair.
By the way, you can do it in a much quicker (less code) way:
if(place.equals(birdList.get(bird)) {
b.addObservation();
}
else {
birdList.put(bird, place);
}
As assumed, the error is located in BirdData.observe(). In particular it's a false condition:
birdList.get(b) will return a String and is compared to bird which is a Bird. In consequence, b.addObservation() will never be executed.
As I'm not exactly familiar with the expected logic of your program I can only give hints on how to solve this. Please take in mind to choose carefully, which of the following will fit your requirements:
public void observe (Bird bird, String place) {
bird.addObservation();
}
This ignores the place parameter, but some other comments already pointed out, that the place info itself isn't used too much anyway. Maybe it's not intended to be used here.
OR
replace
if (birdList.get(b).equals(bird)){
with
if (bird.equals(b) && birdList.containsKey(b) && birdList.get(b).equals(place)){
(You can obviously save the birdList.containsKey(), if you place the for loop in an else condition on the following if condition.)
This considers both bird and place.
Right now you are restricting your bird sightings to only one location by using a HashMap<Bird, String>. I think it would be more useful to allow for multiple locations to be stored for each bird by saving the locations in a HashSet<String> inside the bird object.
If you want to use a HashMap to search for Bird objects at that point it gets a little tricky, but you can use the Bird object as both the key and value in the HashMap.
So in the Bird Object, add this:
HashSet<String> locations;
And then for observing you can do something like this:
Map<Bird, Bird> birdList = new HashMap<>();
public void observe (Bird bird, String place) {
Bird retreivedBird = birdList.get(bird);
if(retreivedBird != null){
if(!retreivedBird.locations.contains(place)){
retreivedBird.locations.add(place);
}
}else{
retreivedBird = bird;
bird.locations.add(place);
birdList.put(bird, bird);
}
retreivedBird.addObservation();
}
I appreciate all of the help. None of the recommended solutions actually incremented the observation field as need. I ended up rebuilding the BirdData section, creating a HashMap containing Bird and a List. Then to keep count of the observations, I used birdList.size();. This removed the field from Bird entirely solving the issue. Thanks for the feedback.
public abstract class ShapeClass {
private double area;
CONSTRUCTORS
MUTATORS, ACCESSORS
public abstract double calcArea();
}
public class CircleClass extends ShapeClass {
private int diameter;
private double area;
public CircleClass() {
super();
diameter = 10;
}
public CircleClass(CircleClass inCircle) {
super(inCircle);
diameter = inCircle.getDiameter();
}
public CircleClass(int inDiameter) {
setDiameter(inDiameter);
area = calcArea();
super.setArea(area);
}
public void setDiameter(int inDiameter) {
if(validateInt(inDiameter)) {
diameter = inDiameter;
} else {
throw new IllegalArgumentException("invalid diameter");
}
}
public int getDiameter() {
return diameter;
}
public boolean equals(int inDiameter) {
return(diameter == inDiameter);
}
public boolean equals(Object inObj) {
boolean same = false;
if(inObj instanceof CircleClass) {
CircleClass inCircle = (CircleClass)inObj;
if(super.equals(inCircle)) {
if(diameter == inCircle.getDiameter()) {
same = true;
}
}
}
return same;
}
public String toString() {
return (" area of circle is: " + super.toString());
}
private boolean validateInt(int inDiameter) {
boolean valid = false;
if (inDiameter>0) {
valid = true;
}
return valid;
}
private boolean validateReal(double inArea) {
boolean valid = false;
if(inArea>0.0) {
valid = true;
}
return valid;
}
#Override
public double calcArea() {
double radius;
radius = ((double) diameter) / 2.0;
area = Math.PI * radius * radius;
return area;
}
}
This is my code for a ShapeClass. I have two other classes Rectangle and Triangle, they're pretty much the same as the CircleClass.
In another class i'm assigning the ShapeClass objects in an array.
if I do that it'll be something like shape[3] = {Shape Object,Shape Object,Shape Object}. I don't know if that's right, I'm new to java. Sorry if there's any confusion.
My question is if I do that how do I distinguish what object is Circle, Rectangle or Triangle? When I want to print out a circle object only?
Thanks for the help.
You can check by using instanceof :
if(shape[0] instanceof Circle){
// do something
}
So there is an operator in java - instance of:
if(shapeObject instanceof Circle){
//print
}
so you can use it to distinguish objects by type. Also as for your question whether it's correct: You can use this approach with creating array of parent object type and putting children in it. After that, if you call toString method on each object from that array specific implementation of that method will be invoked. For example if there is Circle object in this array and there is overridden toString method in it then after calling toString on object from array of ShapeObject specific implementations will be invoked.
Try like this,
for(int i = 0; i < shapeArray.length; i++){
if(shapeArray[i] instanceof CircleClass){
// print circle here
}
}
You have 2 options:
// Solution 1: prits out all instances of Circle, basically also all subclasses of Circle
for (ShapeClass shape : shapes) {
if (shape instanceof CircleClass)
System.out.println(shape.toString());
}
// Solution 2: Matches exact class
for (ShapeClass shape : shapes) {
if (shape.getClass().equals(CircleClass.class))
System.out.println(shape.toString());
}
The above solutions will solve the task you asked about. But maybe the information below will be userful for you:
What if you want to print out the names of each shape, how to distingush them in this case?
Let's say we have 3 shapes:
public class Shape {
public void print() {
System.out.println("Shape is printed");
}
}
public class Triangle extends Shape {
#Override
public void print() {
System.out.println("Triangle is printed");
}
}
public class Circle extends Shape {
#Override
public void print() {
System.out.println("Circle is printed");
}
}
This code will print exactly what you need, because you defined the same function for all of the shapes, overriding it in child classes, and the appropriate function will be called based on object type determined at the runtime:
for (Shape shape : shapes) {
shape.print();
}
I have a class called a Plane.
class Plane {
private int _planeId;
public int getModel() { }
public int getNumberOfPassengers() {}
}
And I another class called PlaneService which depends on plane and adds some logic to it,
class PlaneService {
private Plane _plane;
public PlaneService(Plane _plane) {
this._plane = _plane;
}
public void validdatePlane(int planeId) {
fetch plane from planeId from db.
if ( plane.getNumberOfPassengers() is in range of {100 to 300} )
plane is valid.
}
}
But now a new requirement comes in: plane must be extended to support fighter jets. So new design looks like this:
class Plane {
private int _planeId;
public int getModel() { }
}
class PassengerPlane extends Plane {
public int getNumberOfPassengers() {}
}
class FigherJet extends Plane {
public boolean isCommissioned() {}
}
My question is how can I best design 'PlaneSvc'in OOP way ? Is there a good design pattern ?
Currently, my code looks like this:
class PlaneService {
private Plane _plane;
public PlaneService(Plane _plane) {
this._plane = _plane;
}
public void validdatePlane(int planeId) {
fetch CommercialPlane from planeId from db.
if (commericialPlaneObject != null) {
if ( plane.getNumberOfPassengers() is in range of {100 to 300} )
plane is valid.
}
fetch FighterPlaneObject from planeId from db.
if (FighterPlaneObject != null) {
if (fighterplane.isCommissioned()) {
return validPlane;
}
}
}
}
I am sure there is some design pattern to deal with such a case. I need to understand a cleaner approach to if-else here.
What you have here is the strategy pattern and you can find it here.
I dont thing you should pass planeId to the method because you have attached an plane to the PlaneService in the constructor which means that no service without a plane, i also assume that plane has the planeId in it.
If you want the implementation not to be bound at compile time you should use bridge pattern. More or less is the same but you use it for structural purpuses and you pass the delegator not in the constructor but with a setter method.
You could define a validate method in the plane class, for example:
class Plane {
private int _planeId;
public boolean validate(){
return false;
}
public int getModel() { }
}
and then in the child classes, you could override the behavior of the validate method:
class FigherJet extends Plane {
public boolean isCommissioned() {}
#Override
public boolean validate() {
return isComissioned();
}
}
class PassengerPlane extends Plane {
public int getNumberOfPassengers() {}
#Override
public boolean validate(){
//if plane.getNumberOfPassengers() is 100 to 300, return true, else return false
}
}
And then your plane service can call the validate() method on any of the child objects:
public boolean validatePlane(int planeId) {
//fetch passenger plane from planeId from db.
if (passengerPlane != null) {
return passengerPlane.validate();
}
}
You can use Visitor patter for this case as well.
class Plane {
private int _planeId;
public int getModel() { }
abstract boolean validateWith(PlaneValidator validator);
}
class PassengerPlane extends Plane {
public int getNumberOfPassengers() {}
boolean validateWith(PlaneValidator validator) {
return validator.validate(this);
}
}
class FigherJet extends Plane {
public boolean isCommissioned() {}
boolean validateWith(PlaneValidator validator) {
return validator.validate(this);
}
}
class PlaneService implements PlaneValidator {
...
boolean validatePlane(int planeId) {
//fetch Plane object from db
return plane.validateWith(this);
}
//Methods implemented from PlaneValidator
#Override
boolean validate(FighterJet plane) {
return plane.isCommissioned();
}
#Override
boolean validate(PassengerPlane plane) {
return plane.getNumberOfPassengers() in range(100, 300);
}
}
In this way, you can easily extend your system with new types, all thing you need to do is override validateWith(PlaneValidator) method in derived type and add appropriate method to PlaneValidator and describe its behavior in implemented method. I don't know is it pattern applicable to your system, but for me looks it could be.
I need to write a Java enumeration LetterGrade that represents letter grades A through F, including plus and minus grades.
Now this is my enumeration code:
public enum Grade {
A(true),
A_PLUS(true),
A_MINUS(true),
B(true),
B_PLUS(true),
B_MINUS(true),
C(true),
D(true),
E(true),
F(false);
final private boolean passed;
private Grade(boolean passed) {
this.passed = passed;
}
public boolean isPassing() {
return this.passed;
}
#Override
public String toString() {
final String name = name();
if (name.contains("PLUS")) {
return name.charAt(0) + "+";
}
else if (name.contains("MINUS")) {
return name.charAt(0) + "-";
}
else {
return name;
}
}
What I am confused about is writing the main program. I think it could be quite straightforward but I have no clue on how to start it.
I don't want the whole code. Just a few lines to give me a head start. The rest I will try to figure out on my own.
I imagine you have a Student class that looks like this:
class Student {
protected Grade grade = null;
public Student(Grade g) {
this.grade = g;
}
}
Then you simply add a method in this class calling the isPassing method from your enum:
public boolean isPassing() {
if (this.grade != null)
return this.grade.isPassing();
return false;
}
This is supposing the passed boolean in Grade are correctly set and are invariant.