I like consolidating my code/classes as much as possible without each class itself getting messy. So I looked into using NestedClasses, though InnerClasses in this case because the InnerClass needs access the OuterClass's members.
Example
Lets say I have a program that calculates various shape attributes to shapes. So given a Rectangle Shape, it would find the Area/Perimeter from inputs of length and width.
I would first create an abstract class Shape, which has abstract methods getArea() and getPerimeter(). I would then create my subclass RectangleShape, extend the shape class, #Override those methods with the necessary logic.
Now there's a shape Rectangular Prism (Cube). It has the same variables/methods as RectangleShape does, but with one extra, height. In the past I would create another subclass of RectangleShape and go from there.
Is it better/not worse to use an InnerClass instead and have an abstract class PrismShape? I ask this because Prisms share the same methods, no matter the shape. If you're at all confused by the above I'm posting code below of what I'm saying.
Example Code
Shape Class
public abstract class Shape {
public abstract double getArea();
public abstract double getPerimeter();
}
PrismShape Class
public abstract class PrismShape{
public abstract double getVolume();
public abstract double getSurfaceArea();
public abstract double getLateralArea();
}
RectangleShape Class
import Abstract.Shape;
import Abstract.ShapePrism;
public class RectangleShape extends Shape{
//Variables Declared
private double _length, _width;
//Constructor
public RectangleShape(double _length, double _width) {
setLength(_length);
setWidth(_width);
}
//Getters and Setters
#Override
public double getArea() {
return getLength() * getWidth();
}
#Override
public double getPerimeter() {
return (2 * getLength())+ (2 * getWidth());
}
public double getLength() {
return _length;
}
private void setLength(double _length) {
this._length = _length;
}
public double getWidth() {
return _width;
}
private void setWidth(double _width) {
this._width = _width;
}
//Inner Class Prism
public class RecPrismShape extends PrismShape{
//Variables Declared
private double _height;
//Constructor
public RecPrismShape(double _height) {
setHeight(_height);
}
//Getters and Setters
#Override
public double getSurfaceArea(){
return (getLateralArea() + (2 * getArea()));
}
#Override
public double getVolume(){
return getArea() * getHeight();
}
#Override
public double getLateralArea(){
return getPerimeter() * getHeight();
}
public double getHeight() {
return _height;
}
private void setHeight(double _height) {
this._height = _height;
}
}
}
I'm open to criticism, still fairly new to Java. My thought process during this was I have 2d Shape attributes and 3d (Prism) shape attributes. The 3d Shapes derive their attributes from 2d shapes, but not visa versa. So for me at least having InnerClasses makes sense.
My own take on this: A public inner class seems most useful when the rest of the program has an object of the outer class, and it wants to create an object of the inner class that "belongs" to the outer class object in some way; that is, it's tightly associated with it.
The way you've arranged things, however, it means that if the client wants to create a RecPrismShape object, it has to first create a RectangleShape object that the prism object will belong to. Most likely, this is not going to be useful. That is, the client creates a RectangleShape rect just because it has to, in order to create a RecPrismShape, and the rect object wouldn't be useful to it in any other way.
I think a better idea would be to have a RecPrismShape object have a private RectangleShape object as one of its fields, but this would be an "implementation detail". That way, you'd get to reuse the RectangleShape code, which it seems like you're trying to do.
public class RecPrismShape extends RectangleShape {
private RectangleShape rect;
private double height;
public RecPrismShape(double length, double width, double height) {
rect = new RectangleShape(length, width);
this.height = height;
}
// and just one example of how you could use it
public double getVolume() {
return rect.getArea() * getHeight();
}
}
Related
I have three classes. Class A is titled Circle. Class B is titled ColorfulCircle. Class C is titled ColorfulBouncingCircle. I need to inherit the methods public double getCenterY(), public double getCenterX, and public void setCenterCoordinates(double centerX, double centerY) from Class “A” Circle so that I can use them in Class “C” ColorfulBouncingCircle.
Circle looks like this:
class Circle {
private double centerX, centerY;
public double getCenterX() {
return centerX;
}
public double getCenterY() {
return centerY;
}
public void setCenterCoordinates(double centerX, double centerY) {
this.centerX = centerX;
this.centerY = centerY;
}
}
There are the exact methods I need to be able to use in ColorfulBouncingCircle so that I can use the centerX and centerY variables in code over there.
I just need to know exactly what do I type in to the ColorfulBouncingCircle class so that I can use them.
Thank you.
Extend the Circle class from ColorfulBouncingCircle class.
public class ColorfulBouncingCircle extends Circle {
}
You can then call getCenterX(), getCenterY() and setCenterCoordinates() from the object of ColorfulBouncingCircle class.
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!
My friend gave me this task and I am struggling with the last to, it asks me to:
"implement a class called Square that represents a square. Class
Square must be derived from Rectangle. Make sure you override
toString()."
I don't even think I am even close to getting it but any help would be great
Rectangle.Java
public class Rectangle {
public double width;
public double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
public double getArea() {
return width * height;
}
public double getPerimeter() {
return 2*width+2*height;
}
#Override
public String toString() {
return "Rectangle[width "+width+",height "+height+"]Area:"+getArea()+",Perimeter:"+getPerimeter();
}
public static void main(String[] args) {
double width = (10);
double height = (10);
Rectangle rectangle = new Rectangle(width, height);
System.out.println(rectangle);
}
}
Sqaure.java
public class Sqaure extends Rectangle {
private final double width, height, area, perimeter;
public Sqaure(double width, double height) {
this.width = width;
this.height= height;
}
public static void main(String[] args) {
double width = (10);
double height = (10);
Sqaure sqaure = new Sqaure(width, height);
System.out.println(square);
}
}
There is no need to overwrite more than the constructor and toString(). As a square is just a special rectangle with equal side lengths, you can just initialize them to the same value, and all other methods will work as expected:
public class Square extends Rectangle {
public Square(double width) {
super(width, width);
}
#Override
public String toString() {
return "Square[width:" + width + "]Area:" + getArea() +
",Perimeter:" + getPerimeter();
}
Note that in the real world, you probably wouldn't use inheritance in this case, as this introduces some ambiguity -- you can still create squares with the rectangle constructor, and people may get mislead to use instanceof checks to determine whether a given rectangle is a square. Instead, one would probably add a single parameter constructor and check for width/height equivalence in toString.
You should note that sub and super classes do not need a main-class. You should have a separate main class where you initialize these objects.
To override a method use #Override. You do this because you can initialize a subclass a super class, e.g., Rectangle square = new Square(...). When you call square.toString() the output should not be Rectangle[width...], but Square[width...].
#Override
public String toString() {
return return "Square[width "+size+",height "+size+"]Area:"+getArea()+",Perimeter:"+getPerimeter();
}
If you do not override a method the functionality will be the same as of the super class (which is just fine for getArea() and getPerimeter().
Please note: a Square usually only has one parameter instead of two, because that is what makes it a Square. ;)
What your "friend" probably wants you to do is to use a super constructor. As it was already explained by Peter Lawrey, you do not need to define width, height in your extended class. It is considered a bad practice to hide fields in such a way. Square class will inherit those fields from its superclass Rectangle on the account of the extends keyword:
public class Sqaure extends Rectangle
This is how you might use a super constructor in your case.
public Sqaure(double side) {
super(side, side);
}
This will call the super class's constructor:
public Rectangle(double width, double height)
and by doing so, it will assign the Square's inherited fields width and height to the same value, making it a square. The inherited methods getArea() and getPerimeter() will still work, so there is no need to override them.
You will need to override the toString() method, because it has the word Rectangle in it. I am sure you can figure that one out yourself.
I was asked today in a interview what is the Interface Segregation Principle and what is the opposite case or principle to this one.
The ISP is clear for me but I don't know the second part of the question, what is the opposite principle to the ISP?
From Wikipedia:
The interface-segregation principle (ISP) states that no client should be forced to depend on methods it does not use.
The opposite of that would be a client that is forced to depend on methods that it doesn't use. This might manifest itself in either implementing an interface that it doesn't require, the interface having methods at too broad of a layer, or a class that has several abstract methods defined that are not necessary to the client.
An example (first with interfaces):
public interface Book {
String getAuthor();
String getGenre();
String getPageCount();
String getWeight();
}
public interface EBook extends Book {
// Oh no - ebooks don't have weight, so that should always return zero!
// But it makes no sense to include it as an attribute of the interface.
}
An example with abstract methods:
public abstract class Shape {
public abstract double getVolume();
public abstract double getHeight();
public abstract double getLength();
public abstract double getWidth();
public abstract Color getColor();
}
public class Line extends Shape {
public double length;
public Color color;
// Kind of forced to have a volume...
public double getVolume() {
return 0;
}
/// ...and a height...
public double getHeight() {
return 0;
}
// ...and a width...
public double getWidth() {
return 0;
}
public double getLength() {
return length;
}
public Color getColor() {
return color;
}
}
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;
}
}