Java why is implementing an interface necessary? - java

I've just started Java, and are going through examples online at:
http://docs.oracle.com/javase/tutorial/java/IandI/usinginterface.html
Then I got to implementing an interface, while I understand the concept behind it, but it seems weird to me, as in the interface declaration you only defines it, and in the class that implements this interface you'll still have to write it's functions. So why use it at all?
I tried the sample code, and then change the code to remove the interface, and they both work the same. So my question is when will implementing interface be used? It looks unnecessary to me. Thanks in advance!
Sample Code online:
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;
}
}
Code that I changed to, taken out the interface, it still works the same
public class RectanglePlus {
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(RectanglePlus otherRect) {
if (this.getArea() < otherRect.getArea())
return -1;
else if (this.getArea() > otherRect.getArea())
return 1;
else
return 0;
}
public static void main( String[] args )
{
RectanglePlus newRect = new RectanglePlus(20, 30);
RectanglePlus somerect = new RectanglePlus(50, 100);
System.out.println("Area of newRect is " + newRect.getArea());
System.out.println("Area of somerect is " + somerect.getArea());
if((newRect.isLargerThan(somerect))==1)
{
System.out.println("newRect is bigger");
}
else
{
System.out.println("somerect is bigger");
}
}
}

Two reasons:
If you will have more than one implementation of the interface. Say you have Shape and subtypes is Rectangle, Oval, etc. If you want to write code that can do something with shapes in general, you need an interface which all of the subtypes implement - the interface is the set of methods you know that any Shape will have.
If you are writing an API - you are writing a library which someone else will use. You provide other people with interfaces - this is the stuff that it's okay for them to call. You will implement the interface, and the implementation class may have more methods - and you would like to be able to change those methods later, but your users should be able to pick up the new version of your library and use it with their old code. By separating the interface from the implementation, you give the public something they can use, but preserve for yourself something you can change without hurting existing users.

This is to facilitate type/interface reuse. You can pass a sub-type's object where a parent type object is expected. You can refer to http://www.oodesign.com/liskov-s-substitution-principle.html.
This basically allows you to deal in an abstract way. Your program can handle objects of different Classes as long as they implement certain behavior (or implement an interface or extend from a class)

If you implements Relatable it allows you to find the largest object in a pair of objects, for any objects that are instantiated from a class that implements Relatable. Otherwise you only can find the largest object in a pair of objects that are instantiated from the same class.

Related

How to make a class operate with math operation in java? [duplicate]

This question already has answers here:
Operator overloading in Java
(10 answers)
Closed 5 years ago.
I have the following class, which describe one point on XY surface:
class Point{
double x;
double y;
public Point(int x, int y){
this.x = x;
this.y = y;
}
}
So I want to overlad + and - operators to have possibility write run following code:
Point p1 = new Point(1, 2);
Point p2 = new Point(3, 4);
Point resAdd = p1 + p2; // answer (4, 6)
Point resSub = p1 - p2; // answer (-2, -2)
How can I do it in Java? Or I should use methods like this:
public Point Add(Point p1, Point p2){
return new Point(p1.x + p2.x, p1.y + p2.y);
}
Thanks in advance!
You cannot do this in Java. You'd have to implement a plus or add method in your Point class.
class Point{
public double x;
public double y;
public Point(int x, int y){
this.x = x;
this.y = y;
}
public Point add(Point other){
this.x += other.x;
this.y += other.y;
return this;
}
}
usage
Point a = new Point(1,1);
Point b = new Point(2,2);
a.add(b); //=> (3,3)
// because method returns point, you can chain `add` calls
// e.g., a.add(b).add(c)
Despite you can't do it in pure java you can do it using java-oo compiler plugin.
You need to write add method for + operator:
public Point add(Point other){
return new Point(this.x + other.x, this.y + other.y);
}
and java-oo plugin just desugar operators to these method calls.
There is no operator overloading in Java. Apparently for reasons of taste. Pity really.
(Some people will claim that Java does have overloading, because of + with String and perhaps autoboxing/unboxing.)
Let's talk about value types.
Many early classes (and some later ones) make a right mess of this. Particularly in AWT. In AWT you should be explicitly making copies of simple values all over the place. Almost certainly you want to make value types immutable - the class should be final and it should never change state (generally all final fields pointing to effective immutables).
So:
public final class Point {
private final int x;
private final int y;
private Point(int x, int y) {
this.x = x;
this.y = y;
}
public static of(int x, int y) {
return new Point(x, y);
}
public int x() {
return x;
}
public int y() {
return y;
}
public Point add(Point other) {
return of(x+other.x, y+other.y);
}
// Standard fluffy bits:
#Override public int hashCode() {
return x + 37*y;
}
#Override public boolean equals(Object obj) {
if (!(obj instanceof Point)) {
return false;
}
Point other = (Point)obj;
return x==other.x && y==other.y;
}
#Override public String toString() {
return "("+x+", "+y+")";
}
}
The original code was confused between int and double, so I've chosen one. If you used double you should exclude NaN. "Point" tends to imply an absolute point, which doesn't make sense to add. "Vector" or "dimension" would probably be more appropriate, depending upon what you intend.
I've hidden the constructor, as identity is not important. Possibly values could be cached. Possibly it is, say, common to add a point to a zero point, so no points need to be created.
It's possible you might want a mutable version, for example to use as an accumulator. This should be a separate class without an inheritance relationship. Probably not in simple cases, but I'll show it anyway:
public final class PointBuilder {
private int x;
private int y;
public PointBuilder() {
}
public PointBuilder(Point point) {
this.x = point.x;
this.y = point.y;
}
public Point toPoint() {
return new Point(x, y);
}
public PointBuilder x(int x) {
this.x = x;
return this;
}
public PointBuilder y(int y) {
this.y = y;
return this;
}
public PointBuilder add(Point other) {
this.x += other.x;
this.y += other.y;
return this;
}
}
You cannot do this in Java because there is no operator overloading in Java.
You have to use the second option you have mentioned:
Edit: You can add the Add method in the Point class itself
public Point Add(Point other){
return new Point(this.x + other.x, this.y + other.y);
}
You cannot overload operators in java. You will need handle this in Point class.
You cannot override operators in Java. That's one of the reasons why any nontrival math (especially geometric) operations should not be implemented in Java (the Point class above is kind of such a class, if you want it to do some real work, for example a line-line intersection, you'd better do it in C++).

I'm having difficulties understanding how the "interface" function is useful in Java?

I've looked up the "interface" function several places, but nowhere does it seem to actually explain the benefits of using it, or why I should use interfaces when writing my own future programs.
I finished the exercise below, where I used an interface named "Form" to describe the methods "circumference" and "area". Then I have 3 classes "Circle", "Rectangle" and "Square" where the variables from each form are input and calculated to finally retrieve the circumference and area of each form.
My problem is that after I finished the exercise, I'm struggling to really see the point of implementing this "Form" interface. I feel like I could have just ignored using an interface and then simply through inheritance, make each of the classes inherit the circumference and area methods and then just create objects for each of the forms at the end when compiling?
How did the interface make things easier for me?
public class FormCompiling {
public static void main(String[] args) {
Form[] f = {new Circle(1.5), new Rectangle(2.0,3.0), new Square(2.5)};
System.out.println("Area:");
for(int i = 0 ; i<f.length; i++) {
System.out.println(f[i].area());
}
}
}
public interface Form {
public double circumference();
public double area();
}
public class Circle implements Form {
double radius = 0;
double area = 0;
double circumference = 0;
Circle(double radius) {
this.radius = radius;
}
#Override
public double circumference() {
circumference = 2 * radius * Math.PI;
return circumference;
}
#Override
public double area() {
area = radius * radius * Math.PI;
return area;
}
}
public class Rectangle implements Form {
double length = 0;
double width = 0;
double area = 0;
double circumference = 0;
Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
#Override
public double circumference() {
circumference = (2 * length) + (2 * width);
return circumference;
}
#Override
public double area() {
area = length * width;
return area;
}
}
public class Square extends Rectangle implements Form {
Square(double length) {
super(length, length);
this.length = length;
}
#Override
public double circumference() {
circumference = 4 * length;
return circumference;
}
#Override
public double area() {
area = length * length;
return area;
}
}
Yes, you could have a parent class with empty methods (or some of them implemented).. and you'd get a similar result. However, you would not get compile errors if you forgot to implement some of the methods.
An interface "forces" you to follow some contract; a parent class does not.
In fact, an interface is a contract.
Whoever decides to implement it, has to implement the contract.
interface = the "what" = contract = specification
class = the "how" = implementation
The biggest use case for interfaces in Java is to facilitate Polymorphism. Polymorphism means having a single class behave like multiple other classes. Multiple inheritance is not supported in Java so you can't extend more than one class, but you can implement multiple interfaces. There are many useful docs about this topic, here is an official one from oracle to get you started: https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html
Interfaces are also useful as a "social contract" between a designer of a class/program and the developer who implements it. By implementing an interface you promise that your implementation follows specific behaviors. This allows for consistency amongst different implementations, which is especially useful when trying to collaborate with many developers on a single, large project.

How can i return a value from an overridden method in the superclass AND the method in the subclass?

I realized I had this issue when i was typing down simple code to find the perimeter and rectangle to demonstrate method overriding in java. can i return the area (length * breadth) in the same subclass method?
package override;
class perimeter{
int length,breadth;
perimeter(){length = breadth = 0;}//default constructor
perimeter(int length, int breadth){
this.length = length;
this.breadth = breadth;
}
int show(int length, int breadth){
return 2*(length + breadth);
}
}
class area extends perimeter{
area(int length, int breadth){
super(length,breadth);
}
int show(int length, int breadth){
return super.show(length, breadth);
// how can i return this too? : return length * breadth;
}
}
public class overrideshapes {
public static void main(String args[]){
area shape1 = new area(5,10);
System.out.println(""+ shape1.show(shape1.length,shape1.breadth));
}
}
I don't know what are you trying to do, but I'm going to explain a few more what I'm thinking about your question.
I think you want to calculate perimeter and areas for different polygons, so the best way is to create an Interface, something like this.
public Interface Calculate {
public int calculateArea(int length, int width);
}
Then you should to implement your interface, in many clase according your polygons, for example:
public class Square implements Calculate {
#Override
public int calculateArea(int length, int width){
return length*width; //Because this is the way you calculate square areas
}
}
So you have to implement for your polygons your interface method "calculateArea" using #Override annotation, so each polygon knows how to calculate its area.
Hope it helps to you.

New to Java: SuperClass and SubClass

I am fairly new to Java and I am learning about Inheritance. I am trying to create a subclass called BetterRectangle under the superclass Rec1.
Rec 1 gets the x and y coordinates (location) and also gets the width and height (size) of the rectangle. BetterRectangle calculates the perimeter and area of the rectangle.
I get errors in the main method. It cannot find any of the symbols (i.e. cannot find rec1.getHeight(20) symbol).
public class Rec1 {
private double x;
private double y;
private double width;
private double height;
public void setLocation(double xCord, double yCord) {
x = xCord;
y = yCord;
}
public void setSize(double h, double w) {
height = h;
width = w;
}
public double getHeight(double h) {
return height;
}
public double getWidth(double w) {
return width;
}
}
public class BetterRectangle extends Rectangle {
public BetterRectangle(int x, int y, int width, int height) {
super(x, y, width, height);
super.setLocation(x, y);
super.setSize(width, height);
}
public double calcPerimeter() {
return super.getHeight() * 2 + super.getWidth() * 2;
}
public double calcArea() {
return super.getHeight() * super.getWidth();
}
}
Look closely:
Rectangle Rec1 = new Rectangle();
Rec1.getHeight(20);
The type of Rec1 is Rectangle. But the Rectangle class doesn't have a getHeight method. Maybe you wanted this:
Rec1 rec1 = new Rectangle();
rec1.getHeight(20);
Notice that I renamed the variable to rec1, and changed its type.
class BetterRectangle is extending Rectangle in your sample code. So here BetterRectangle would be child and Rectangle would be parent. Now BetterRectangle uses super keyword to access getHeight,getWidth etc...functions. since these functions are not present in Rectangle class it is giving compilation Error.
Instead of extending Rectangle class extend Rec1 class in BetterRectangle and then run the main Class Rectangle. This should work.
Look carefully here
Rectangle BetterRectangle = new Rectangle();
Rectangle Rec1 = new Rectangle();
You are declaring variables of type Rectangle instead of your own classes. I can't see your import statements but you are likely creating types of java.awt.rectangle. You're mixing up variable types and variable names. When creating instances of your own classes it should look like this:
Rec1 mySimpleRec = new Rec1();
BetterRectangle myBetterRec = new BetterRectangle()
When declaring things put them in this order "Type variableName = new Type()" or "Class variableName = new Class()".

Java - making Triangle class

I need to make a Class named "TriangleShape" which impliments java.awt.Shape.
Now another Class "TriangleComponent" should have an object of TriangleShape class and it should draw a triangle, with the given length of sides.
I managed to create it, but i've read that the triangle should be drawn in the following way:
TriangleShape t = new TriangleShape(30,40,50);
g2.draw(t); //This is the Graphics2D object that I use in paintComponent
The following is the code that I created, but it uses Line2D to create a triangle.
It is the TriangleShape class, assume that I have implimented all the methods of the Shape Class.
public class TriangleShape implements java.awt.Shape{
private double a, b, c;
private int x,y;
private Point2D loc;
public TriangleShape() {
this.a=0;
this.b=0;
this.c=0;
}
public TriangleShape(double a, double b, double c) {
//if supplied dimensions form a valid Triangle
if ( this.isValid(a,b,c) ) {
this.a = a;
this.b = b;
this.c = c;
}
//Otherwise make it zero sized triangle
else{
this.a=0;
this.b=0;
this.c=0;
}
}
public void resize(double a, double b, double c) {
if ( this.isValid(a,b,c) ) {
this.a = a;
this.b = b;
this.c = c;
}
//else let size remain unchanged
}
public TriangleShape getRandomTriangle() {
TriangleShape t = new TriangleShape(5,8,9);
return t;
}
public double area(){
double area, s;
s = (a+b+c)/2;
area = Math.sqrt(s *(s-a) * (s-b) * (s-c));
return area;
}
private boolean isValid(double a, double b, double c) {
double s = (a+b+c)/2;
if ( ((s-a) * (s-b) * (s-c)) <= 0 )
return false;
else
return true;
}
public double perimeter() {
double p;
p = a+b+c;
return p;
}
public double getA(){
return a;
}
public double getB(){
return b;
}
public double getC(){
return c;
}
public void setLocation(Point2D location){
loc = location;
}
public Point2D getLocation(){
return loc;
}
public double getX(){
return loc.getX();
}
public double getY(){
return loc.getY();
}
And the TriangleComponent class:
public class TriangleComponent extends JComponent{
TriangleShape t;
double alpha, beta, gamma;
double a,b,c;
double X,Y;
#Override
protected void paintComponent(Graphics g) {
//super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
t = new TriangleShape(100,100,190);
t.setLocation(new Point2D.Double(100,500));
a = t.getA();
b = t.getB();
c = t.getC();
X = t.getX();
Y = t.getY();
///////////////Drawing Base line.....
g2.draw(new Line2D.Double(X,Y,(X+c),Y)); //line c...
g2.draw(new Line2D.Double((X+c), Y, ((X+c)+a*Math.cos(Math.PI+getBeta())), (Y+a*Math.sin(Math.PI+getBeta())))); //line a...
//JOIning the last end points
g2.draw(new Line2D.Double(X, Y, ((X+c)+a*Math.cos(Math.PI+getBeta())), (Y+a*Math.sin(Math.PI+getBeta()))));
System.out.println("X1 = "+X+" Y1 = "+Y);
System.out.println("X2 = "+(X+c)+" Y2 = "+Y);
System.out.println("X3 = "+((X+c)+a*Math.cos(Math.PI+getBeta()))+" Y3 = "+ (Y+a*Math.sin(Math.PI+getBeta())));
//System.out.println("Alpha = "+getAlpha());
System.out.println("Gamma = "+(getGamma()*180)/Math.PI);
}
public double getAlpha(){
double temp = Math.acos(((Math.pow(c, 2)+Math.pow(b, 2))-Math.pow(a, 2))/(2*b*c));
System.out.println("Alpha = "+temp+" Degrees");
return temp;
}
public double getBeta(){
double temp = Math.acos(((Math.pow(c, 2)+Math.pow(a, 2))-Math.pow(b, 2))/(2*a*c));
System.out.println("Beta = "+temp+" Degrees");
return (temp);// * Math.PI)/180;
}
public double getGamma(){
double temp = Math.acos(((Math.pow(a, 2)+Math.pow(b, 2))-Math.pow(c, 2))/(2*b*a));
System.out.println("Gamma = "+temp+" Degrees");
return (temp);// * Math.PI)/180;
}
}
This works, but I need a way to draw the triangle without relying on Graphics2D or drawing it directly with the paintComponent method. Is there a way to do this?
According to the JavaDoc of the Graphics2D class Shapes are rendered according to the following principle:
Shape operations
If the operation is a draw(Shape) operation, then the createStrokedShape method on the current Stroke attribute in the Graphics2D context is used to construct a new Shape object that contains the outline of the specified Shape.
The Shape is transformed from user space to device space using the current Transform in the Graphics2D context.
The outline of the Shape is extracted using the getPathIterator method of Shape, which returns a PathIterator object that iterates along the boundary of the Shape.
If the Graphics2D object cannot handle the curved segments that the PathIterator object returns then it can call the alternate getPathIterator method of Shape, which flattens the Shape.
The current Paint in the Graphics2D context is queried for a PaintContext, which specifies the colors to render in device space.
In short, this means that the Graphics2D.draw(Shape) method will call your TraingleShape.getPathIterator(AffineTransform) method and use the returned PathIterator object in order to find which points to draw lines between.
As such, you will likely be required to implement your own PathIterator implementation that corresponds to your TriangleShape implementation.
The above solution may however be more complex then it needs to be. An alternative would be to look into the Path2D class which allows you to easily specify arbitrary shapes using simple operations such as lineTo(x,y). Since this class implements the Shape interface you could allow your TriangleShape class to extend this class, or just delegate to it. Here is an example of using the GeneralPath class, which works in a similar way to Path2D:
http://www.roseindia.net/java/example/java/swing/graphics2D/general-path.shtml
It does however depend on your particular assignment whether this would be an acceptable solution or not.

Categories

Resources