I have a problem when I use inheritance and define an object of parent class then call the constructor from the child class which has its own properties. When i want to assign values to the child class using sets methods its gives me an error (cannot find symbol)
this is my code
public class Shape {
private final double PI =3.14;
public Shape() {
}
public double getPI() {
return PI;
}
}
public class Rectangle extends Shape {
private double length;
private double width;
public Rectangle() {
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
}
public class Circle extends Shape{
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
}
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
Shape s[] = new Shape[3];
int type;
for (int i = 0; i < s.length; i++) {
System.out.println("Enter the Shape:\n 1.Rectangle \n 2.Circle");
type = in.nextInt();
if(type==1){
s[i] = new Rectangle();
s[i].setLength(5.5);
}
}
}
Your problem lies here:
s[i] = new Rectangle();
s[i].setLength(5.5);
Yes. You know that this form is an instance of Rectangle, all the JVM knows is that it's a Shape. If you want to use it as a Rectangle, you have to declare it as one:
Rectangle r = new Rectangle();
r.setLength(5.5);
s[i] = r;
EDIT: The reason for this is, when you declare an instance as a Shape (parent class), the JVM will consider it to be this, even if your code suggests (to a human reader) that a specific type will be used, the JVM will not make any assumptions on which sub class will be instantiated.
You are limited to the possibilities of the class you declared it to be.
Since you now again save it as a Shape, in your array, if later on you'll want to get that value, you'll need to cast it.
Rectangle rNew = (Rectangle)s[index]; // of course after checking whether it is in fact a Rectangle
you setLength() method is present in your sub class Rectangle while s[i] points to an instance of type Shape which is a super class. thus, it doesn't recognize the instance method due to implicit upcasting.
you will have to explicitly downcast you object s[i] from shape to Rectangle.
This is how you can do it:
Rectangle r = (Rectangle)s[i];
r.setLength(5.5);
NOTE: Ofcourse the above statements gos after s[i] = new Rectangle();
an ideal way though (as explained by #Stultuske):
Rectangle r = new Rectangle();
r.setLength(5.5);
s[i] = r;
Related
I created an array to hold different shapes. Circle and Square are abstract classes extended from Class Shape. Cube and Sphere are from the interface called ThreeDShape. I need to find the area for all shapes and the area and volume for the 3D shapes and call them using an array. I got the Test class to be able to use the abstract methods. How do I get the test class to use the interface methods? How do I print the abstract methods AND the interface methods in a single array?
I also need to call the details of each class from within the array using the getClass() method.
public class Test {
public static void main(String[] args) {
Shape [] shape = new Shape[4];
Circle circle = new Circle();
shape[0] = circle;
Shape sphere = new Sphere();
shape[1] = sphere;
Shape cube = new Cube();
shape[2] = cube;
Square square = new Square();
shape[3] = square;
for(Shape shape1 : shape) {
System.out.println("The area of " + shape1.getClass() +" is " + shape1.area());
System.out.println("The volume of " + shape1.getClass() +" is " + shape1.volume());
System.out.println("Found in " + shape1.getClass());
System.out.println(" ");
}
}
}
public interface ThreeDShape {
public abstract double volume();
}
public class Cube implements ThreeDShape{
double a = 5;
public double volume() {
return a*a*a;
}
public double area() {
return 6*a*a;
}
}
public class Square extends Shape {
double s = 5;
public double area() {
return s*s;
}
}
public class Circle extends Shape {
double r = 9;
public double area() {
return r*r*3.14;
}
}
public class Sphere implements ThreeDShape {
double r1 = 5;
public double volume() {
return ( 4.0 / 3.0 ) * Math.PI * Math.pow( r1, 3 );
}
public double area() {
return 4*3.14*r1*r1;
}
}
public abstract class Shape {
public abstract double area();
protected abstract double volume();
}
```
Your design is wrong.
Everything should be a subclass of Shape. If you want some specialization then Sphere and Cube should be subclasses of ThreeDShape that is subclass of Shape. So to do what you do you just call a super method of Shape that has different implementation (aka is overwritten) on every subclass.
The loops becomes just this:
for (Shape s: shapes){
s.myBeautifulMethod();
}
If you want to keep ThreeDShape as an interface then Sphere and Cube should be both Shape and ThreeDShape:
public class Sphere extends Shape implements ThreeDShape { [...] }
public class Cube extends Shape implements ThreeDShape { [...]}
but I would stick with a single hierarchy, since otherwiese you are moving forward to multiple inheritance, and this is not very Java.
You are asking for a reflective logic where is not needed at all.
Hope I helped.
If you want to do this, you need to check the type of each shape and cast as you loop through the array. Something like:
for(Shape shape1: shape) {
System.out.println("Area: " + shape1.area());
if(shape1 instanceof ThreeDShape) {
System.out.println("Volume: " + ((ThreeDShape) shape1).volume());
}
}
Generally, type checking and casting like this should be avoided - it probably indicates bad program design. Interfaces and abstract classes are designed for situations where you have multiple types that support the same API. Here, though, you have 2 different APIs: Shape and ThreeDShape.
What I prefer is to avoid instanceOf, getClass and so on
public interface OperationalShape {
double getVolume();
double getArea();
String getName();
boolean supportsVolume();
}
public class Circle implements OperationalShape {
public double getVolume() {
throw new CustomUnsupportedException();
{
public boolean getArea() {
return ...
}
public String getName() {
return "Circle";
}
public boolean supportsVolume() {
return false;
}
}
After that you can iterate on your collection of OperationalShapes, checking with an if(supportsVolume()) if you should call getVolume() or not. You can get the name via getName().
For this code to compile ,
1)You need to change the Shape class to Shape interface. because interface can only implement an interface and not class.
or
2)Change ThreeDShape to class and extends to Shape class
ThreeDShape sphere = new Sphere();
shape[1] = sphere;
1 type implementation
public class Test {
public static void main(String[] args) {
Shape [] shape = new Shape[4];
Circle circle = new Circle();
shape[0] = circle;
ThreeDShape sphere = new Sphere();
shape[1] = sphere;
ThreeDShape cube = new Cube();
cube.volume();
shape[2] = (Shape) cube;
Square square = new Square();
shape[3] = square;
int x = 3;
int z = 1;
for(Shape shape1 : shape) {
System.out.println("The area of the circle is " + shape1.area());
System.out.println("The volume of the circle is " + shape1.volume());
x++;
z++;
System.out.println("Found in " + shape1.getClass());
System.out.println(" ");
}
}
}
interface ThreeDShape extends Shape{
public abstract double volume();
}
class Cube implements ThreeDShape{
double a = 5;
public double volume() {
return a*a*a;
}
public double area() {
return 6*a*a;
}
}
class Square implements Shape {
double s = 5;
public double area() {
return s*s;
}
#Override
public double volume() {
// TODO Auto-generated method stub
return 0;
}
}
class Circle implements Shape {
double r = 9;
public double area() {
return r*r*3.14;
}
#Override
public double volume() {
// TODO Auto-generated method stub
return 0;
}
}
class Sphere implements ThreeDShape {
double r1 = 5;
public double volume() {
return ( 4.0 / 3.0 ) * Math.PI * Math.pow( r1, 3 );
}
public double area() {
return 4*3.14*r1*r1;
}
}
interface Shape{
double area();
double volume();
}
As the other answers mentioned, the design is wrong. This is how I would do it.
If you have to use interface and abstract class in one project, you need to think which of them is more generic. In this class, is Shape or ThreeDShape more generic? Ofcourse, ThreeDShape is a kind of Shape.
Hence, Shape should be an interface and ThreeDShape an abstract class that implements the Shape interface, and not the other way around. An abstract class can implement an interface without actually implementing its methods, but an interface cannot extend an abstract class.
public interface Shape {...}
public abstract class ThreeDShape implements Shape {...}
public class Circle implements Shape {...} // Same for Square
public class Cube extends ThreeDShape {...} // Same for Sphere
I have class Shape2D, in that class I have method that calculate circle area circleArea, also I have class CircleArea where I store all atributes that I need for my method. Also, my class CircleArea extends class Shape2D. So, How I can implement my method from class Shape2D into class CircleArea.
This is my Shape2D class:
public class Shape2D {
public static void areaCircle(Circle c) {
double circleArea = Math.pow(c.getR(), 2) * Math.PI;
}
}
And this is my Circle class:
public class Circle extends Shape2D {
private double r;
public Circle() {
}
public double getR() {
return r;
}
public void setR(double r) {
this.r = r;
}
}
To implement one of the methods from the Shape2D class in the Circle class, you could do:
Shape2D.areaCircle(circleObject);
The above line can be called in the Circle class. Don't forget to pass in an actual circle object into the function.
You have a static method inside of 2D shape, meaning you can use it in any class without having 2DShape instantiated. This also means that you do not need the circle class to extend 2DShape to use this method, but I imagine you are going for that parent child relationship for the OO paradigm. If you don't want the method to be called from any class, remove static from the method. If you wish to call it statically inside of your Circle class constructor, first instantiate r to something, and then pass it into the static method call.
public class Circle extends Shape2D {
private double r;
public Circle() {
r=1;
Shape2D.areaCircle(this);
}
public double getR() {
return r;
}
public void setR(double r) {
this.r = r;
}
}
Note that your static function doesn't actually return anything, so it calculates the area and the value is lost. You can fix this inside of shape2D by changing the return type of circleArea to double in stead of void, and returning the result appropriately.
public static double areaCircle(Circle c) {
double circleArea = Math.pow(c.getR(), 2) * Math.PI;
return circleArea;
}
or non-statically, and protected in stead of public (either will work)
protected double areaCircle(Circle c) {
double circleArea = Math.pow(c.getR(), 2) * Math.PI;
return cricleArea;
}
If you wanted to do the same thing, but removed the static flag from the method, then you can use super to call parent methods.
public class Circle extends Shape2D {
private double r;
public Circle() {
r=1;
super.areaCircle(this);
}
public double getR() {
return r;
}
public void setR(double r) {
this.r = r;
}
}
Now if you wanted to actually store the area inside of this circleObject, I would create another attribute for the Circle class, and modify your constructor as such. Perhaps even adding a constructor that takes an int argument for radius (or in the future, an area with some way to differentiate the two that can get the radius value).
public class Circle extends Shape2D {
private double r;
private double area;
//Default Constructor
public Circle() {
r=1;
this.area = super.areaCircle(this);
}
//Radius constructor
public Circle(double rad) {
this.r = rad;
this.area = super.areaCircle(this);
}
public double getR() {
return r;
}
public void setR(double r) {
this.r = r;
}
}
It's also worth mentioning that you should look at the scope of these methods you create, and what you are trying to accomplish with them. For instance, you have your circleArea method defined as public, when it could be defined as protected and function similarly for this case. Protected means that the method can be used inside of the class, as well as all subclasses (children of the parent class, like circle). You can read information about these closures here. Also, when working with object inheritance, you should get into the habit of using the this keyword to reference which methods/attributes you actually wish to retrieve. Info on this keyword.
I realize this is a lot to take in, but if you have any questions feel free to comment!
I am having difficulty extending the calCir class to the main class
I have a constructor that gives
class calCir {
double radius;
calCir(double r) {
radius = r;
}
double AreaCircle() {
return Math.PI * (radius * radius);
}
double CircumferenceCircle() {
return 2 * Math.PI * radius;
}
}
I would like to use Main extends calCir but get an error due to the constructor
class Main{
public static void main(String args[]) {
error: constructor calCir in class calCir cannot be applied to given types;
class Main extends calCir
Im fairly new to Java so im still confused as to how I would use inheritance
Here is the full code if needed
https://repl.it/NA5S/8
This error is due to following reason:
when you create a constructor for a class, there won't be any default constructor created for that class. so if you extend that class and if the subclass tries to call the no-arg constructor of its super class then there will be an compile-time error.
As stated here: Constructor in class cannot be applied to given types
You have created an explicit constructor for your class. Any explicitly defined constructor will eliminate the default no-args constructor that Java will use implicitly.
Here is the constructor you have created:
CalCir(double r) {
radius = r;}
In order to use inheritance as requested, you can do any of the following.
Remove the explicit constructor from the parent class.
Insert a second construction with no parameters into the parent class:
CalCir()
{
// Set the radius to default of zero
this(0);
}
Override the default constructor in the child class:
public class MainSubClass extends CalCir
{
public MainSubClass()
{
// Set the radius to default of zero
super(0);
}
public static void main(final String args[])
{
// Insert program here
}
}
First, it is meaningless to have Main extend CalCir in this case.
Second, go back to the specific question you asked.
When you have a class (e.g. Child) extend from another (e.g. Parent), in the ctor of Child, it ALWAYS needs to invoke constructor of its parent. If you are not EXPLICITLY invoking any, compiler will automatically assume you are invoking the no-arg constructor of parent.
e.g.
class Child extends Parent {
Child() {
// do something
}
}
is equivalent to
class Child extends Parent {
Child() {
super();
// do something
}
}
If in Parent, a constructor with arguments is declared, but there is no-arg ctor declared:
class Parent {
Parent(int foo) {...}
}
it is illegal for Child to invoke the no-arg ctor of Parent, because it simply does not exists.
So you need to explicitly tell the compiler which ctor you want to invoke:
class Child extends Parent {
Child() {
super(123);
// do something
}
}
Any particular reason why you need to extend CalcCir? Your CalCir has a constructor which requires 2 args, if you are to extend it to your main class, then you would have create a constructor in main like:
public Main(double radius) {
// define your params to parent here or have it passed in constructor...
super(param1, param2); // matching your super class
}
Based on the link you provided though, it seems to be more appropriate this way:
Your main class which contains your starting point:
public class Main {
public static void main(String[] args) {
Scanner b = new Scanner(System.in);
while (true) {
try {
System.out.println("Determining the area/perimeter of a 2D shape.");
System.out.println("Choose a shape:\n\nRectangle --> (Type a or rectangle)\nCircle --> (Type b or circle)");
String shape = b.nextLine();
if ((shape.equalsIgnoreCase("Rectangle")) || (shape.equalsIgnoreCase("a"))) {
System.out.println("Input Length");
double length = b.nextDouble();
System.out.println("Input width");
double width = b.nextDouble();
Shape rectangle = new Rectangle(length, width);
System.out.println("Area of rectangle is " + rectangle.getArea());
System.out.println("The perimeter is " + rectangle.getPerimeter());
if (length == width){
System.out.println("This is a special type of reactangle, a square!");
}
break;
} else if ((shape.equalsIgnoreCase("circle")) || (shape.equalsIgnoreCase("b"))) {
System.out.println("Input Radius");
double radius = b.nextDouble();
Shape circle = new Circle(radius);
System.out.println("Area of circle is " + circle.getArea());
System.out.println("The circumference is " + circle.getPerimeter());
break;
} else {
System.out.println("Not valid choice\n");
}
} catch (Exception e) {
System.out.println("Not valid choice\n");
}
}
}
}
Then your Circle and Rectangle classes:
public class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
#Override
double getArea() {
return Math.PI * (radius * radius);
}
#Override
double getPerimeter() {
return 2 * Math.PI * radius;
}
}
public class Rectangle extends Shape {
private double length;
private double width;
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
#Override
double getArea() {
return length * width;
}
#Override
double getPerimeter() {
return 2 * (length + width);
}
}
Of which both inherited from shape
public abstract class Shape {
abstract double getArea();
abstract double getPerimeter();
}
I'm trying to create a generic class that compares objects in an array list and returns the largest. My issue is that I'm not quite sure I understand completely how generics work.
Measurable:
import java.util.ArrayList;
/**
Describes any class whose objects can be measured.
*/
public abstract class Measurable<T>{
abstract double getMeasure();
public static <T extends Measurable<T>> T getLargest(ArrayList<T> objects){
T largest = objects.get(0);
for(int i = 0; i < objects.size(); i ++){
if(largest.getMeasure() == objects.get(i).getMeasure()){
largest = objects.get(i);
}
}
return largest;
}
}
Box:
import java.awt.Rectangle;
import java.util.ArrayList;
public class Box extends Measurable {
private Rectangle box;
private static ArrayList<Rectangle> rectangles;
public Box(){
box = new Rectangle();
rectangles = new ArrayList<Rectangle>();
}
public ArrayList<Rectangle> create(){
for(int i = 0; i < 10; i++){
box = new Rectangle((int) Math.random(), (int) Math.random());
rectangles.add(box);
}
return rectangles;
}
#Override
public double getMeasure() {
double area = 0;
for(int i = 0; i < rectangles.size(); i++){
area = rectangles.get(i).getWidth()*rectangles.get(i).getHeight();
}
return area;
}
public static void main(String[] args){
Box b = new Box();
b.getLargest(b.create());
}
}
I'm coming across an issue where it says "The method getLargest(ArrayList) in the type Measurable is not applicable for the arguments (ArrayList)" but shouldn't I be able to use any object for the getLargest class?
As you wrote it, getLargest expects the objects passed to it in the List to implement Measurable, but java.awt.Rectangle does not.
When you write
public static <T extends Measurable<T>> T getLargest(ArrayList<T> objects){
that declares a T that is different, but named the same, as the T in the Measurable class as a whole, which is likely to lead to total confusion.
If you actually replace T with Rectangle in your code, you can see that you're trying to call Rectangle.getMeasure(), which is a method that does not exist.
I am not really sure where generics come into play here. It seems like you want to make a bunch of shapes that are derived from a base class Measurable. You also want the abstract class to hold some code for working with Measurable subclasses. Basically you need to make a subclass that implements Measurable. I think what you want a Box class like the one below.
public class Box extends Measurable {
private double width;
private double height;
public Box(double width, double height){
this.width = width;
this.height = height;
}
public double getMeasure() {
double area = width*height;
return area;
}
}
edit2
Sorry never mind I just added
public double cylinderSurfaceArea() {
return 2 * base.circleArea() + base.circleCirumference() * 2 * height;
}
}
With no error codes. This would be correct?
edit:
Thank you to all those who have answered. I have since changed my previous Cylinder class to read. Now I want to take it a step further and add
public double cylinderSurfaceArea() {
return 2 * Math.PI * radius * radius + 2 * Math.PI * radius * h;
}
However it now says that radius (or even r) returns an error "cannot find symbol - variable radius). Shouldn't the symbol be found/declared from the Circle class?
What I am trying to do is calculate the volume of a cylinder using a separate Circle.java class.
So for instance, I have the following so far for my circle.java
public class Circle {
public double radius;
public Circle(double r) {
radius = r;
}
public double circleArea() {
return Math.PI * radius * radius;
}
public double circleCirumference() {
return Math.PI * 2 * radius;
}
}
Now here are where the questions start. When making the Cylinder class do I start with:
public class Cylinder extends Circle {
If so, overall I have:
public class Cylinder extends Circle {
public Circle base;
public double height;
public Cylinder(double r, double h) {
height = h;
base = new Circle(r);
}
public double getVolume() {
return base.circleArea * height;
}
}
However, I keep getting an error after:
public Cylinder(double r, double h) {
Stating that:
constructor Circle in class Circle cannot be applied to given types; required:double; found: noarguments; reason:actual and formal arguments lists differ in length."
Can someone push me in the right direction? What am I doing wrong?
That happens because the first call of you constructor is implicit super()
Quote from the Java Tutorials:
If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error.
You need to make a parameterless constructor in your Circle class or change your Cylinder constructor like this:
public Cylinder(double r, double h) {
super(r);
height = h;
}
You're implicitly calling the super constructor with no argument, but there's no such constructor.
But you have a design problem : You're trying to use both composition and inheritance. One would be enough.
Using inheritance :
public class Cylinder extends Circle {
public double height;
public Cylinder(double r, double h) {
super(r);
height = h;
}
public double getVolume() {
return circleArea() * height;
}
}
Using composition (almost always better) :
public class Cylinder {
public Circle base;
public double height;
public Cylinder(double r, double h) {
height = h;
base = new Circle(r);
}
public double getVolume() {
return base.circleArea * height;
}
}
You don't need an explicit base field in Java when using inheritance. To initialise the base class (or "superclass"), you need to use the super statement in your child class constructor:
class Circle {
public Circle(double radius) {
// …
}
}
class Cylinder extends Circle {
public Cylinder(double radius, double height) {
super(radius); // calls the parent class constructor
// …
}
}
Alternately, you could use composition instead of inheritance - probably a better design in this case:
class Circle {
public Circle(double radius) { /* … */ }
}
class Cylinder { // no `extends` here
public Cylinder(Circle base, double height) {
// …
}
public Cylinder(double radius, double height) {
this(new Circle(radius)); // calls the above constructor
// …
}
}
(I'm omitting trivial assignments and fields in the above code sample for brevity.)
Problem 1:
The problem in your program is no default constructor present in your Circle. While creating the Cylinder object its looking for the default constructor in Circle.
if you modify your Circle as below it will work
class Circle {
public Circle(){
}
}
problem 2
There is "base.circleArea" method only present in Circle, you have forgot "()"
base.circleArea need to change to base.circleArea().
public class Cylinder extends Circle {
public double getVolume() {
return base.circleArea() * height;
}
}
Problem 3
Your Cylinder should be like below. You are already extended circle so no need to create variable Circle base inside Cylinder.
class Cylinder extends Circle {
public double height;
public Cylinder(double r, double h) {
super(r);
height = h;
}
public double getVolume() {
return circleArea * height;
}
}