How do I use static field of subclass in super class method - java

I have a code on my super class that want WIDTH and HEGHT from subclass to calculate
public SuperClass{
public Vector2 getCenter(){
float x = this.position.x + WIDTH/2;
float y = this.position.y + HEIGHT/2;
return new Vector2(x, y);
}
public void setCenter(Vector2 position){
float x = position.x - WIDTH/2;
float y = position.y - HEIGHT/2;
setPosition(new Vector2(x, y));
}
}
I have to use static field of WIDTH and HEIGHT but it compilation error cause super class still don't know where is WIDTH and HEIGHT. Can I have static field that overrided in subclass?

You can't do that. The whole point of polymorphism is that super classes know nothing about child classes!
In other words: dependency flows "upwards" only. A child class depends on its superclass, but not vice versa.
If at all, you can do something like this:
public abstract class SuperClass {
protected abstract int getWidth();
to then call getWidth() within your base class algorithms; and your child classes then have to implement those methods - that is how you actually do proper OO design following the Open/closed principle.
So, the solution here is: you step back and do some more reading on OO design; how to do it; and how it actually works with Java. And for the record: you really want to stay way from using static - that is an abnormality in good OO design; and should only be used when you have really good reasons to do so!

Related

What is the correct way of using the use and this keyword in java?

So I'm extending the Java Rectangle class. And I happen to be a bit confused with the use of this and super and when each should be used. I understand that super is the super class (parent class) and this is the current class you're calling it from.
I currently have a BetterRectangle class extending from the Rectangle class and a method:
boolean isCongruent(Rectangle r)
{
if(r.width == super.width && r.height == super.height)
{
return true;
}
return false;
}
Does it matter if I use this.width and this.height instead of super?
Which would be the more correct way of using regardless both give me the same answer?
If your subclass has field width (and height), then super.width's value can be different than this.width depending on how you initialize the fields. Here is a quick test:-
import java.awt.*;
public class BetterRectangle extends Rectangle {
public int width;
void testWidth() {
System.out.println("width = " + width);
System.out.println("this.width = " + this.width);
System.out.println("super.width = " + super.width);
}
}
--
public static void main(String[] args) {
Rectangle rect = new BetterRectangle();
rect.width = 10; //sets the value of super class's field
((BetterRectangle) rect).width = 90; //sets the value of subclass's field
((BetterRectangle) rect).testWidth();
}
This prints:-
width = 90
this.width = 90
super.width = 10
Note that width and this.width prints the same thing because of data hiding. You'll have to add the super keyword to access the super class's field.
If you don't have a width variable in your subclass, then super.width and this.width point to the same field, so why not just use width?
Hope this helps.
Does it matter if I use this.width and this.height instead of super?
If your subclass has inherited the attributes from its superclass (in this case, Rectangle's width and height), then your subclass now owns width and height as its own attributes.
So if your intention is to access the subclass' attributes, using this (which refers to the class itself) will make more sense isn't it? So I will go with using this.
Attributes inherited to child:
class Parent{
protected int width = 5;
protected int height = 5;
}
class Child extends Parent{
public Child(int width, int height){
this.width = width;
this.height = height;
}
public int getHeight() {
return this.height;
}
public int getWidth() {
return this.width;
}
public int getSuperHeight() {
return super.height;
}
public int getSuperWidth() {
return super.width;
}
}
Test Run:
Child c = new Child(2, 3);
System.out.println(c.getWidth() + " " + c.getHeight()); //2 3
System.out.println(c.getSuperWidth() + " " + c.getSuperHeight()); //2 3
Like what ScarryWombat mentioned, if the attributes are masked by the attributes declared in the subclass, then using this and super makes a difference. this now refers to the attributes declared within the subclass instead of the inherited attributes.
Attributes inherited to child, but masked:
class Child extends Parent{
private int width;
private int height;
public Child(int width, int height){
this.width = width;
this.height = height;
}
public int getHeight() {
return this.height;
}
public int getWidth() {
return this.width;
}
public int getSuperHeight() {
return super.height;
}
public int getSuperWidth() {
return super.width;
}
}
Test Run:
Child c = new Child(2, 3);
System.out.println(c.getWidth() + " " + c.getHeight()); //2 3
System.out.println(c.getSuperWidth() + " " + c.getSuperHeight()); //5 5
In general, there should hardly ever be a genuine need to use either this. or super.
Looking at your iscongruent() method, ask yourself how it could ever return false. Answer : that's only possible if the super class and the sub class both have a member of the same name, that is, there are multiple distinc fields named 'width' and/or 'height'. That's bad practice.
Why is that so ? Suppose these fields are supposed to carry the same semantics. At all time. So then why are there two distinct appearances of the field ? It's plain redundancy and that's a source of bugs. Eliminate one of the two and you're out of the problem. Suppose contrariwise that these fields can possibly carry different semantics. You likely want to expose those semantics in your sub class at least through a getter (and perhaps a setter too). So now you have getters (and perhaps setters) in both your super and sub classes with identical signatures but differing semantics. That's plain anti-design-by-contract. Sub classes should never alter the semantics of methods established by their super class. And finally, if you don't want to expose the same-named field in the sub class, there's nothing to stop you from just naming it 'localWidth' or 'subWidth' or whatever other name that provides a better and more detailed explanation of the intended semantics.
That said, here are some cases where using 'this' and/or 'super' is warranted or even unavoidable :
In constructors, when setting fields from the value of a parameter that has been given the same name as the field :
this.x = x; /* x = x would mean an assignment to the method parameter, not the field */
In overriding implementations, when you also need to execute the code as defined in the super class :
method ( ... ) {
super.method( ... );
/* some extra code here to deal with the extra state in the sub class */
}
There may be more, but in general abundant use of 'this' and 'super' leads to too much 'noise' that can be avoided without harming readability. Of course that's just a matter of opinion and of preferred style.
The best way may be is to look at how standard Java classes accesses the variables. javax.swing.text.DefaultCaret extends Rectangle. Except where there are local variable clashes - the access of variables do not use any this or super specifiers. I would stick to that :).
For example, this is the repaint method:
protected final synchronized void repaint() {
if (component != null) {
component.repaint(x, y, width, height);
}
}

Java: cannot reference height before supertype constructor has been called

I'm trying to create a class Figure with subclasses like rectangle, triangle and circle. However, when I try to compile them I get the same error in all of them, which makes me believe that the error is in the Figure class. The error: cannot reference height before supertype constructor has been called.
Figure:
public abstract class Figure{
public double width;
public double height;
public Figure(double width, double height){
this.width = width;
this.height = height;
}
public abstract double area();
public abstract double perimeter();
}
Ellipse:
public class Ellipse extends Figure{
private double a;
private double b;
public Ellipse(){
a = width/2;
b = height/2;
}
public double area(){
return (Math.PI * a * b);
}
public double perimeter(){
return (2 * Math.PI * Math.sqrt((Math.pow(a,2) + Math.pow(b,2)))/2);
}
}
Thank you very much.
So your constructor for Ellipse does not call the inherited constructor of Figure. Yet you are are trying to use variables of Figure that are assigned values in the constructor of Figure. You need to update your Ellipse constructor to call the super with values. I recommend the following.
public Ellipse(int w, int h){
super(w,h);
a = width / 2;
b = width / 2;
}
You need call super class constructor in Ellipse:
public Ellipse(){
super(_width, _height)
a = width/2;
b = height/2;
}
You need to initialized you height and width, that are currently present in your Figure class. You can do this by specifically calling the Figure constructor from Ellipse, something like this.
public Ellipse(){
super(23, 23);
a = width /2;
b = height/2;
}
The super() method calls your Figure constructor, which will then initialized height and weight allowing you to use them to calculate a and b accordingly.
Every class has to call the constructor of its superclass as the first instruction in each of its own constructors[1]
This is done implicitly if the superclass has a default constructor (one without parameters). But if it has only a constructor with parameters, then you have to write that call yourself. You do that by using the word super and passing the appropriate parameters.
This is done so that the logical part of the current class that is inherited from the superclass can properly be initialized.
You have two possible solutions:
Add a default constructor to Figure. Perhaps one with default width and height of zero:
public Figure() {
this( 0.0, 0.0 );
}
This makes sense if there is a sensible default value for the width and height.
Change the constructors of the subclasses so that they accept (at least) width and height as well:
public Ellipse(double width, double height){
super(width, height);
a = width/2;
b = height/2;
}
This makes sense if there is no sensible default for the width and height.
The way you have tried doing this, there would be no values for width and height, so you couldn't possibly use them in the subclass (e.g. width/2 would be zero, because there was nothing that put any value in width, because nobody called the constructor of Figure). When you create an instance, there is no other place where the superclass constructor that sets width and height will be called - therefore all constructors have to start by calling their superclass constructors first.
[1] It's also OK to call one of the other constructors of the same class - if it has more than one - provided that ultimately, the constructor that gets called calls one of the supeclass constructors.
You need to call super as the very first thing in each constructor of every subclass of Figure:
public Ellipse(double ewidth, double eheight){
super(ewidth, eheight);
a = width/2;
b = height/2;
}
That is necessary because you use width and height, which are a member of Figure and are only getting initialized when the Figure constructor is executed, which is what the super call does. You basically used an uninitialized variable.
So why did I call the new parameter ewidth instead of width? Would I have named them width, the fields of the same name in the parent class would have been obscured by the local variable of the same name. In your example that would not have been a problem because the code path in both constructors is dead simple, but I'd like to raise awareness for this because it is a source of obscure bugs :)
Similar question has already been answered.
Refer to this:
java call superclass from a subclass constructor?
To add that if you had a non-parameterised constructor in your superclass then you wouldn't have to place an explicit call to the constructor of the superclass.
Also check this:https://docs.oracle.com/javase/tutorial/java/IandI/super.html
There is a note on this page: 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. Object does have such a constructor, so if Object is the only superclass, there is no problem.

Need help to write a translate method in my segment method

I am trying to write a translate method in a segment class. My variables are p1 = x1, y1 and p2 = x2, y2. How can I create a translate method using these two variables?
I wrote my translate method in my Point class as:
public void translate(int xmove, int ymove) {
x += xmove;
y += ymove;
}
Here my variables are x and y, simple! But for my segment class I am confused and not sure how to put them in the code.
If this is a geometric segment, then it ought to be defined in terms of two Points (a line segment) or two Points and a radius (circular segment), or something along those lines.
In that case, it should have some private fields that store the Point data. Translating the whole segment just means translating each Point in the class.
So if it's a line segment, and you have
class Segment {
Point start;
Point end;
//...
}
then you'd just need
class Segment {
Point start;
Point end;
public void translate(int xmove, int ymove) {
start.translate(xmove,ymove);
end.translate(xmove,ymove);
}
}
This is good design because it reuses your Point class in defining the Segment, and uses Point methods to define Segment methods.
But it does depend a little on quite what you mean by "segment"...
I am not 100% sure this is what you want, but assuming you would like to translate a segment of 2 points
class Segment{
Point point1;
Point point2;
//constructor
public void translateSegment(int xmove, int ymove){
point1.translate(xmove,ymove);
point2.translate(xmove, ymove);
}
}
If you change the method in the point class to private, you will need to do something else. This code is based on the fact that your translate method for a point is public. There are advantages and disadvantages to having an object mutable, and this is a design question you should consider.

Area of an object- Abstract Class - Java

I am learning Java using the book Java: The Complete Reference. Currently I am working on the topic of abstract classes.
Please Note: There are similar questions on stackoverflow. I searched them but I couldn't understand the concept.
If I run the below program, it produces the correct output, but I didn't understand the concept.
What is the need of reference variable of an Abstract class here. I can get the output without the reference variable of an abstract class.
First I ran the below program and got the desired output.
abstract class Figure {
double dim1;
double dim2;
Figure(double a, double b) {
dim1 = a;
dim2 = b;
}
// area is now an an abstract method
abstract double area();
}
class Rectangle extends Figure {
Rectangle(double a, double b) {
super(a, b);
}
// override area for rectangle
double area() {
System.out.println("Inside Area for Rectangle.");
return dim1 * dim2;
}
}
class Triangle extends Figure {
Triangle(double a, double b) {
super(a, b);
}
// override area for right triangle
double area() {
System.out.println("Inside Area for Triangle.");
return dim1 * dim2 / 2;
}
}
class AbstractAreas {
public static void main(String args[]) {
Rectangle r = new Rectangle(9, 5);
Triangle t = new Triangle(10, 8);
Figure figref;
figref = r;
System.out.println("Area is " + figref.area());
figref = t;
System.out.println("Area is " + figref.area());
}
}
And I tried the below code without creating/using abstract class reference.
class AbstractAreas {
public static void main(String args[]) {
Rectangle r = new Rectangle(9, 5);
Triangle t = new Triangle(10, 8);
// Figure figref;
// figref = r;
System.out.println("Area is " + r.area());
// figref = t;
System.out.println("Area is " + t.area());
}
}
It also gave the same output as the first program.
Can anyone please explain what is the need of calling "area method" using abstract class reference.
It's meant simply as a demonstration that even though you declared the variable as the abstract type, you can assign an instance of a concrete subclass to it and get the overriden behavior from the subclass.
Practical use example would be if you needed a collection of them:
List<Figure> figureList = new ArrayList<Figure>();
figureList.add(new Rectangle(9, 5));
figureList.add(new Triangle(10, 8));
for (Figure f : figureList) {
System.out.println(f.area());
}
Or if you want to pass any subclass of Figure to a method that used the area():
public void printArea(Figure f) {
System.out.println("Area is: " + f.area());
}
...
myObject.printArea(new Rectangle(9, 5));
myObject.printArea(new Triangle(10, 8));
In Abstract classes you can define abstract as well as non abstract methods. However the 1st concrete subclass of the Abstract class must implement those abstract methods. You cannot create instance of Abstract classes and they must be subclassed to some concrete class.
Also note JLS states if abstract classes have all abstract method it is better to use interface.
Can anyone please explain what is the need of calling "area method" using
abstract class reference.
Concept is same as inheritance. We use abstract classes to avoid duplicate.
What is the need of reference variable of an Abstract class here. I can get the
output without the reference variable of an abstract class.
Abstract class is used as a reference because you can take advantage of polymorphism here. If you call area() on the reference variable at runtime it will call the corresponding implementation of Traingle or Rectangle based on the actual instance type.
Hey here you're using a concept of UPCASTING which is also known as Parent reference to the child object . And the above code program which u have written is performing UPCASTING. Let us look what is UPCASTING.
Upcasting is a mechanism of using parent class reference to refer the child class objects.
Whenever you use Upcasting you can access only the parents class members ( both variables and methods) and the overridden methods of parent class.
In your example the method area() has been overidden in the child classes Rectangle and Triangle so they can be accessed using parent reference figref .
One of the advantage of UPCASTING is we can achieve Dynamic Method Dispatch or Dynamic Polymorphism which is very much necessary in writing complex applications having complex class hierarchies.
Since u mentioned you're using Complete reference Check out the section Dynamic Method Dispatch which comes after method overriding .
Hope this answer Helps :)
Yes you can get the same answer But it is always preferred to use abstract classes or intefaces to call any api.
area() is an api which is overridden in Rectangle or Triangle.

Instance variable initialized in constructor of class becomes null in overridden method

Here I have a simple class that extends a class in the ACM graphics library called GRect.
Grect is a basic rectangle that can be drawn to a GCanvas (Also part of ACM).
What I want to achieve is a new object that is a rectangle, but has an attached label that moves with the rectangle.
In my code, I have created a class named labeledRect that extends GRect, and contains an instance variable "rectLabel" that is of type GLabel, that is initialized in labeledRects constructor. I want to override some of GRect's methods so that when labledRect is moved, rectLabel moves with it.
My issue is that despite "rectLabel" being declared as an instance variable, and initialized in the constructor, it becomes NULL in the overridden method "setLocation".
I have also attempted to initialize "rectLabel" at declaration, but the same problem occurs.
import acm.graphics.*;
public class labeledRect extends GRect {
//GLabel declared as an instance variable
public GLabel rectLabel;
public labeledRect(double x, double y, double width, double height, String theLabel) {
//Call GRect constructor
super(x, y, width, height);
//Label initialized.
//Location setting and adding to the canvas works fine here.
rectLabel = new GLabel(theLabel);
rectLabel.setLocation(
x + (width / 2) - (rectLabel.getWidth() / 2),
y + (height / 2) + (rectLabel.getAscent() / 2.2));
}
public void setLocation(double x, double y)
{
//Setting GRect's location. Works correctly./
super.setLocation(x, y);
//Attempt to set the label's location
//and get a NullPointer exception for rectLabel
rectLabel.setLocation(
super.getX() - (rectLabel.getWidth() / 2),
super.getY() - (rectLabel.getHeight() / 2));
}
}
It's hard to reason about exactly what might be setting the variable to null given that it's a public field. That's the first thing you should change. Fields should almost always be private.
Next, you say setLocation is an overridden method - is it called in the GRect constructor by any chance? If so, that will be called before the value is set within the labeledRect constructor, which could well be the cause of your problem.
In Java, the superclass constructor is executed before any of the code in the subclass - both before instance variable initializers and the constructor body. All variables will have their default values. This is why it's a bad idea to call virtual methods from constructors.
(As an aside, the name labeledRect doesn't follow Java naming conventions.)

Categories