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();
}
Related
My Java program is not sorting the outputs. I am not experienced with Java and after looking through similar questions I wasn't able to figure out the issue with my code.
The output shows the 3 spheres and their colors but does not display the radius or sort them by their area like it should.
Below are the 3 .java files involved in my program, I have no errors or warnings in Eclipse so I am assuming I have put some parameter or value in the wrong place... I appreciate any help thanks so much!
ComparableSphere.java
public class ComparableSphere extends GeometricObject implements Comparable<ComparableSphere>{
private double radius;
public ComparableSphere(){
this("white",0);
this.radius = 0;
}
public ComparableSphere(String color, double radius){
super(color);
this.radius = radius;
}
public double area() {
return Math.PI * this.radius * this.radius * 4;
}
public double perimeter() {
return 2 * Math.PI * this.radius;
}
#Override
public int compareTo(ComparableSphere o) {
// TODO Auto-generated method stub
return 0;
}
}
GeometricObject.java
public abstract class GeometricObject {
private String color;
protected GeometricObject(){
this("white");
}
protected GeometricObject(String color) {
this.color = color;
}
public String getColor(){
return this.color;
}
public void setColor(String color){
this.color = color;
}
public abstract double area();
public abstract double perimeter();
public String toString() {
return this.getClass().getSimpleName() + ": color= " + this.color;
}
public boolean equals(Object obj) {
if(!(obj instanceof GeometricObject)){
return false;
}
GeometricObject other = (GeometricObject)obj;
return this.color.equalsIgnoreCase(other.color);
}
}
driver.java
import java.util.ArrayList;
import java.util.Collections;
public class driver {
public static void main(String[] args){
ComparableSphere sphere1 = new ComparableSphere("Purple", 10.1);
ComparableSphere sphere2 = new ComparableSphere("Orange", 3.8);
ComparableSphere sphere3 = new ComparableSphere("Tan", 5.2);
ArrayList<ComparableSphere> sphereList = new ArrayList<ComparableSphere>();
sphereList.add(sphere1);
sphereList.add(sphere2);
sphereList.add(sphere3);
System.out.println("Unsorted list: \n"+sphereList+"\n");
Collections.sort(sphereList);
System.out.println("Sorted list: \n"+sphereList);
}
}
enter image description here
Your compareTo always returns 0, so that means that you are considering all ComparableSphere objects equal to each other, according to the compareTo contract:
Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
This means that Collections.sort thinks it has nothing to do, because all the objects are equal to each other.
You need to write the logic in the compareTo method to make the comparison between this object and the passed-in object and return an appropriate value. This will give Collections.sort the information it needs to sort the list properly.
In the Java 8 tutorial about interface, one example says that when a class implements an interface, one has to type cast the interface type into the class type in order to invoke methods of this class, as shown by the following example from the java 8 tutorial:
public class RectanglePlus
implements Relatable {
public int width = 0;
public int height = 0;
public Point origin;
// four constructors
public RectanglePlus() {
origin = new Point(0, 0);
}
public RectanglePlus(Point p) {
origin = p;
}
public RectanglePlus(int w, int h) {
origin = new Point(0, 0);
width = w;
height = h;
}
public RectanglePlus(Point p, int w, int h) {
origin = p;
width = w;
height = h;
}
// a method for moving the rectangle
public void move(int x, int y) {
origin.x = x;
origin.y = y;
}
// a method for computing
// the area of the rectangle
public int getArea() {
return width * height;
}
// a method required to implement
// the Relatable interface
public int isLargerThan(Relatable other) {
RectanglePlus otherRect
= (RectanglePlus)other;
if (this.getArea() < otherRect.getArea())
return -1;
else if (this.getArea() > otherRect.getArea())
return 1;
else
return 0;
}
}
In the method isLargerThan(Relatable other), other is casted to type RectanglePlus in order to invoke getArea().
In the other example about default methods in interface, the compareTo(Card o) method doesn't type cast o to type PlayingCard, but can invoke int hashCode() directly, I don't understand this. Thanks for your help.
package defaultmethods;
public class PlayingCard implements Card {
private Card.Rank rank;
private Card.Suit suit;
public PlayingCard(Card.Rank rank, Card.Suit suit) {
this.rank = rank;
this.suit = suit;
}
public Card.Suit getSuit() {
return suit;
}
public Card.Rank getRank() {
return rank;
}
public boolean equals(Object obj) {
if (obj instanceof Card) {
if (((Card)obj).getRank() == this.rank &&
((Card)obj).getSuit() == this.suit) {
return true;
} else {
return false;
}
} else {
return false;
}
}
public int hashCode() {
return ((suit.value()-1)*13)+rank.value();
}
public int compareTo(Card o) {
return this.hashCode() - o.hashCode();
}
public String toString() {
return this.rank.text() + " of " + this.suit.text();
}
public static void main(String... args) {
new PlayingCard(Rank.ACE, Suit.DIAMONDS);
new PlayingCard(Rank.KING, Suit.SPADES);
}
}
In short: Because hashCode is defined in java.lang.Object and every other class extends Object implicitly.
So when you have
public int compareTo(Card o) {
return this.hashCode() - o.hashCode();
}
the compiler already knows that o is of type Card which extends Object which defines a hashCode method. No need for an explicit cast.
On the other hand in your isLargerThan method the parameter is of type Relatable:
public int isLargerThan(Relatable other) {
RectanglePlus otherRect
= (RectanglePlus)other;
if (this.getArea() < otherRect.getArea())
return -1;
else if (this.getArea() > otherRect.getArea())
return 1;
else
return 0;
}
And judging from the link you provided, the getArea method is defined in RectanglePlus only. Since the compiler only sees Relatable it does not know anything about a getArea method at this point and you need to explicitly cast other to RectanglePlus to be able to access it.
Note that you should actually do an instanceof check before casting to avoid a ClassCastException when other is not a RectanglePlus (you don't know if there might be other classes implementing Relatable).
Let me try a non-code related example:
If people have a pet they usually give it a name. So whatever pet you have, one can always ask for its name (cf. hashCode). But they cannot ask you to make it bark (cf. getArea) unless they know that it is a dog.
And you will probably fail to make a cat bark (cf. ClassCastException).
first off I tried researching my problem but I have no idea how to word my question ... so I am not sure if there is a question out there that solves my problem and also not sure if this is the best wording for my question either.
So, I have a Superclass Shape
public abstract class Shape {
protected String name;
protected String type;
public Shape(){
name = "";
type = "";
}
public void print (){
System.out.printf("Name = %s, Type = %s", name, type);
}
}
and a Subclass 2D
public abstract class TwoDimensionalShape extends Shape{
protected double length;
protected double area;
public TwoDimensionalShape(double length){
if (length<0.0)
throw new IllegalArgumentException("ERROR: POSITIVE NUMBER REQUIRED");
this.length = length;
type = "Two Dimensional Shape";
}
public abstract void getArea();
#Override
public void print(){
System.out.printf("Name = %s, Type = %s, Length of side = %d, Area = %d",
name, type, length, area);
}
}
along with several smaller subclasses that extend off 2D (and another almost identical class 3D). My problem is with the test code, it doesn't calculate area. Class Test code
Circle S1 = new Circle(2.5);
etc.
shapesArray[0] = S1;
etc.
for(Shape CS : shapesArray){
CS.getArea();
if(CS.Type == "Three Dimensional Shape"){
CS.getVolume();
}
CS.print();
System.out.println(" ");
}
}
I removed the getArea and getVolume methods and the print statement worked fine. Which lead me to think there is a problem with the way each subclass interacts with the superclass, however, the subclass print methods override and return the correct values (except for area :( )
With the area and volume commands, the code doesn't compile and I get this error
ShapeTest.java:25: error: cannot find symbol
CS.getArea();
three times.
Here is one of the subclasses, in case it holds important info needed for a solution.
public class Circle extends TwoDimensionalShape {
public Circle(double length){
super(length);
name = "Circle";
}
#Override
public void getArea(){
area = Math.PI * length * length;
}
#Override
public void print(){
System.out.printf("Name = %s, Type = %s, Radius = %f, Area = %f",
name, type, length, area);
}
}
I am not experienced enough to understand the problem entirely and I have been changing loops, location of variables and methods in the classes but I have not made progress. I thank you for reading this long question and id appreciate any help you can offer.
Your type Shape doesn't declare that method.
The compiler doesn't know that you intend to put TwoDimensionalShape objects into that array. It only see that you said: this array contains Shapes; and shapes do no have those other two methods!
So you could do:
declare that array to contain only TwoDimensionalShape objects. Of course, then you can't add 3D
use if (thing is instanceof TwoDimensionalShape) { and then cast to that type
And then: you dont need a string type. All objects have a class; and that class already defines its exact type. That is why you use instanceof to determine types; not by adding a string field and comparing that string (the wrong way with ==) to other strings!
Your super most class Shape should have all the methods you want to access through polymorphic feature of java.
One would assign a sub-type instance of to a supertype variable to handle all possible subtype classes in a uniform fashion, e.g. using methods declared (but possibly overriden) by the supertype class.
I have made minor changes to your classes.
abstract class Shape {
protected String name;
protected String type;
public Shape() {
name = "";
type = "";
}
public void print() {
System.out.printf("Name = %s, Type = %s", name, type);
}
public abstract void getArea();
public abstract void getVolume();
}
// ----------------
abstract class TwoDimensionalShape extends Shape {
protected double length;
protected double area;
public TwoDimensionalShape(double length) {
if (length < 0.0)
throw new IllegalArgumentException(
"ERROR: POSITIVE NUMBER REQUIRED");
this.length = length;
type = "Two Dimensional Shape";
}
#Override
public void print() {
System.out.printf(
"Name = %s, Type = %s, Length of side = %d, Area = %d", name,
type, length, area);
}
}
//------------------
class Circle extends TwoDimensionalShape {
public Circle(double length) {
super(length);
name = "Circle";
}
#Override
public void getArea() {
area = Math.PI * length * length;
}
#Override
public void print() {
System.out.printf("Name = %s, Type = %s, Radius = %f, Area = %f", name,
type, length, area);
}
#Override
public void getVolume() {
System.out.println("Vaolume method invoked");
}
}
//------------------
public class Dim {
public static void main(String[] args) {
Shape[] shapesArray = new Shape[10];
Circle S1 = new Circle(2.5);
shapesArray[0] = S1;
for (Shape CS : shapesArray) {
if (CS != null) {
CS.getArea();
if (CS.type.equals("Three Dimensional Shape")) {
CS.getVolume();
}
CS.print();
System.out.println(" ");
}
}
}
}
So I have an ArrayList of objects. Inside those objects are various attributes and their values.
The code is pretty simple. GBox and GCircle are childs of GHP. The ArrayList is in World.
What I want to do is print the HP and volume of the box and the HP and diameter of the circle. I understand I could override toString() but I actually want to get the values. What's the correct syntax to do so?
//Main.java
public class Main {
public static void main(String[] args) {
Ini i = new Ini();
}
}
//Ini.java
public class Ini {
private static World w;
public Ini() {
w = new World;
w.makeGBox();
w.makeGCircle();
System.out.println("Box: HP: " +
w.getList().get(0).getHP() +
"Volume: " +
w.getList().get(0).GBox.getVolume());
//compile error no variable GBox in GHP
System.out.println("Circle: HP: " +
w.getList().get(1).getHP() +
"Radius: " +
w.getList().get(1).GCircle.getRadius());
//compile error no variable GCircle in GHP
}
}
//World.java
import java.util.ArrayList;
public class World {
private ArrayList<GHP> list = new ArrayList<>();
public void makeGBox() {
list.add(new GBox());
}
public void makeGCircle() {
list.add(new GCircle());
}
public ArrayList<GHP> getList() {
return list;
}
}
//GHP.java
public class GHP {
private int HP;
public GHP() {
setHP(5);
}
public int getHP() {
return HP;
}
public void setHP(int HP) {
this.HP = HP;
}
}
//GBox.java
public class GBox extends GHP{
private int volume;
public GBox() {
setVolume(10);
}
public int getVolume() {
return volume;
}
public void setVolume(int volume) {
this.volume = volume;
}
}
//GCircle.java
public class GCircle extends GHP{
private int radius;
public GCircle {
setRadius(7);
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
}
Apart from the many compilation problems, you need these changes to achieve what you want.
for (GHP ghp : w.getList()) { // Avoid using get(index) without a forloop, as such
if (ghp instanceof GBox) { // Using the instanceof operator, you can differentiate the 2 class types
System.out.println("Box: HP: " + ghp.getHP() + "Volume: "
+ ((GBox) ghp).getVolume()); // Cast it to GBox to be able to call getVolume
}
if (ghp instanceof GCircle) {
System.out.println("Circle: HP: " + ghp.getHP() + "Radius: "
+ ((GCircle) ghp).getRadius());// Cast it to GCircle to be able to call getRadius
}
}
You would need to cast the generic GHP reference to the specific type like:
((GCircle) ghp).getRadius()
You might also want to have a look on instanceof operator.
The idea being:
for output you override the toString() method because you don't need any class specific information, just print out object details
for class-specific operations you downcast to he specific type
When you read the list values, the only thing the compiler knows, is that the list contains GHP instances.
First check the type and then cast it to the subclass.
GHP ghp = w.getList().get(0);
if(ghp instanceof GBox) {
GBox gbox = (GBox) ghp;
// Here you can access the method getVolume()
/* ... */ gbox.getVolume();
}
A cleaner, more OOP alternative to adding methods to the base class and/or instanceof checks is to use the Visitor pattern that allows you to separate your object structure from any algorithms that operate on them. The algorithm in this case is simply a "display" algorithm.
That said, for most simple cases (like this one) adding methods to the base class and overriding or using instanceof is fine.
List<Shape> shapes = new ArrayList<Shape>();
....
...
for (Shape shape : shapes) {
System.out.println(shape.getHp());
if(shape instanceof Circle){
System.out.println(((Circle) shape).getValuem());
}else if(shape instanceof Box){
System.out.println(((Box) shape).getHieght());
}
try this way..
This is my first class called class circle:
public class circle
{
//circle class begins
//declaring variables
public double circle1;
public double circle2;
public double circle3;
public double Xvalue;
public double Yvalue;
public double radius;
private double area;
//Constructor
public circle(int x,int y,int r)
{//constructor begins
Xvalue = x;
Yvalue = y;
radius = r;
}//constructor ends
//method that gets the area of a circle
public double getArea ()
{//method getArea begins
area = (3.14*(this.radius * this.radius));
return area;
}//getArea ends
public static smaller (circle other)
{
if (this.area > other.area)
{
return other;
else
{
return this;
}
//I'm not sure what to return here. it gives me an error( I want to return a circle)
}
}//class ends
}
This is my tester class:
public class tester
{//tester begins
public static void main(String args [])
{
circle circle1 = new circle(4,9,4);
circle circle2 = new circle(4,7,6);
c3 = c1.area(c2);
System.out.println(circle1.getArea());
//System.out.println(
}
}//class tester ends
The smaller method should have a return type. Also the this keyword cannot be used in a static method. i.e. the method will not have access to the instance of Circle. This make sense given what the method name smaller implies - it compares the current instance of Circle with another passed in.
public Circle smaller(circle other) {
if (this.area > other.area) {
return other;
} else {
return this;
}
}
To use:
Circle smallerCircle = circle1.smaller(circle2);
Aside: Java naming conventions show that class names start with an uppercase letter to give Circle.
Area is unassigned when you make the operation :
c3 = c1.area(c2);
You need to make the GeArea() call before you can use the area field of the class.
So for example:
circle circle1 = new circle(4,9,6);
circle circle2 = new circle(4,7,6);
circle2.area = c1.getArea();
That is assuming that the c3 var you're trying to assign to has been instantiated as a circle.
You simply forgot a closing brace
if (this.area > other.area)
{
return other;
} //You forgot this brace and confused the compiler
else
{
return this;
}