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.
Related
What I assume is that an inherited method will, by standard, use the methods and attributes of the class whose object is used to execute that method.
Here's an example for my question, it's from a task from an older exam:
public class Test {
public static void main(String[] args) {
A a = new A(3);
A b = new B(1, 4);
b.methodOne(6); // <----- This. I think that this uses "b.m" and "b.increase"
}
}
public class A {
private int m;
private int n;
public A(int n) {
m = n;
}
public void methodOne(int i) {
m -= i;
increase(i);
}
public void increase(int i) {
m += 2 * i;
}
public void visilibityTest() {
n++; // <----- I think that b.visibilityTest() would work
// Because it uses the visibility "rights" of A.
}
}
public class B extends A {
private int m;
public B(int m, int n) {
super(n);
this.m = m + 1;
}
public void increase(int i) {
m += i;
}
}
As I said in the comments, I think that by executing b.methodOne, the attribute "b.m" and the method "b.increase" are used, even though methodOne is inherited from class A. (I mean this.m of b, not super.m)
1. Is this true? Do inherited methods normally use the methods and attributes of the subclass?
2. What role do the static/dynamic type play in this task? ("A b = new B")
And what about visibility? In another task I found out that if you use inherited methods to access private attributes of the superclass (that should not be visible to a subclass), you can access those attributes, as if you were accessing superclass's visibility rights. I added an example method called visibilityTest() to show that example on this task. Would that work?
3. Do inherited methods use the visibility of the superclass?
I apologize for any unclear wording. I'm both still trying to understand most of this, and also have to find out what many terms are called like in English, for the purpose of translation.
Any pointing out of unclear wording will be appreciated.
Yes, this is correct. When a method is inherited from a superclass, the subclass can override it to change the behavior, but if not overridden, it will use the implementation in the superclass. In this case, calling b.methodOne(6) will use the m and increase from the B class, since b is an object of type B.
The static type refers to the type of a reference variable (in this case A b) whereas the dynamic type refers to the actual type of the object referred to by the reference variable (in this case B). When you call b.methodOne(6), the static type is A but the dynamic type is B. This means that the method methodOne is resolved based on the type of the object b refers to (dynamic type B) rather than the type of the reference variable b (static type A).
Inherited methods use the visibility of the superclass unless they are overridden in the subclass. In this case, b.visibilityTest() would work, because it is a method in the superclass A and visibility is not changed by inheritance.
If I have three classes as follows:
package com.Bob.Marley;
public class SuperClass{
protected int x = 0;
}
package com.Bob.Marley;
public class SubClass extends SuperClass{
protected int x = 1;
}
package com.Bob.Marley;
public class TestClass{
public static void main (String[] args){
SubClass s = new SubClass();
//print 1
System.out.println(s.x);
//how do I print the superclass variable?
//I know inside SubClass I can access it with plain old super.x
//but what about outside the subclass with a new object.
}
}
So the question is how would I print out 0 from the superclass of the new object s created in a separate class. System.out.println(s.super.x); does not work. I don't think it changes anything but I am using java 8.
The expression s.super.x is invalid here. Whenever you prefix a super.x with something, it should be a type name, not a variable name, e.g. SuperClass.super.x. However, this would be valid only inside the subclass for accessing the superclass of the enclosing class, which does not exist here.
Cast x to be a SuperClass so you can access the x declared in Superclass.
System.out.println( ((SuperClass) s).x);
or
SuperClass sc = (SuperClass) s;
System.out.println(sc.x);
This works because variable access is statically binded. The type of the variable or expression determines the scope searched for variable access.
TL;DR: if you introduce a new field in a subclass, don't re-use a field name from the parent class. You gain nothing, only confusion and problems.
If I understand correctly, you want SubClass instances to have two fields, one inherited from the SuperClass (for the discussion, let's rename that to superX to make things clearer), and one from the subclass itself (let's rename that to subX).
For a given SubClass instance, you want to be able to access both fields, superX and subX (of course, using different expressions). What makes things difficult in your code sample, is the fact that you chose to give both of them the same name x.
So, if you really want your instances to carry both fields, I'd recommend to rename them, so you don't have to use ugly tricks like casting to the SuperClass.
public class SuperClass{
protected int superX = 0;
}
public class SubClass extends SuperClass{
protected int subX = 1;
}
But, if x stands for the same property with the same meaning for both the super and the sub class, just with different initial values, then it doesn't make sense to have two different fields, and you should change the code to become:
public class SuperClass{
protected int x = 0;
}
public class SubClass extends SuperClass{
// constructor initializes the x field with 1.
public SubClass(){
x = 1;
}
}
Of course, then it's impossible to get two different values from a single instance of SubClass.
I want to create data structures to capture the following ideas:
In a game, I want to have a generic Skill class that captures general information like skill id, cool down time, mana cost, etc.
Then I want to have specific skills that define actual interaction and behaviours. So these would all extend from base class Skill.
Finally, each player will have instances of these specific skills, so I can check each player's skill status, whether a player used it recently, etc.
So I have an abstract superclass Skill that defines some static variables, which all skills have in common, and then for each individual skill that extends Skill, I use a static block to reassign the static variables. So I have the following pattern:
class A {
static int x = 0;
}
class B extends A {
static {
x = 1;
}
}
...
// in a method
A b = new B();
System.out.println(b.x);
The above prints 1, which is exactly the behaviour I want. My only problem is that the system complains about I'm accessing static variable in a non-static way. But of course I can't access it in that way, because I only want to treat the skill as Skill without knowing exactly which subclass it is. So I have to suppress the warning every time I do this, which leads me to think whether there is a better/neater design pattern here.
I have thought about making the variables in question non-static, but because they should be static across all instances of the specific skill, I feel like it should be a static variable...
You should generally avoid such use of global state. If you know for sure that the field x will be shared across all instances of all subtypes of the base class, then the correct place to put such a field is probably somewhere other than the base class. It may be in some other configuration object.
But even with your current configuration, it just does't make sense since any subclass that modifies the static variable will make the variable visible to all classes. If subclass B changes x to 1, then subclass C changes it to 2, the new value would be visible to B as well.
I think that the way you described in the question, every subclass should have its own separate static field. And in the abstract base class, you can define a method to be implemented by each subclass in order to access each field:
abstract class A {
public abstract int getX();
}
class B extends A {
public static int x = 1;
public int getX() {
return x;
}
}
class C extends A {
public static int x = 2;
public int getX() {
return x;
}
}
As already pointed out by some answers and comments, your approach won't work the way you want because every static block changes the static variable for all classes extending A.
Use an interface and instance methods instead:
public interface A {
int getX();
}
-
public class B implements A {
private static final int X = 1;
#Override
public int getX() {
return X;
}
}
-
A myInstance = new B();
System.out.println(myInstance.getX()); // prints "1"
CLASS METHODS question: According to D. Flanagan, Java in a Nutshell, 5 edn, pg 102-103, CLASS methods are allowed to be invoked FROM EITHER i) code existing OUTSIDE of the method's class, the standard paradigm, OR from ii) INSIDE the class itself which defines the class method. Here, I believe the standard oo programming paradigm is to put System.out.println statements in a class T method prt(), and then declare a new T object, t1 say, with t1.prt() method called from the outside class, main:
class T {
int x = 4, y = 5;
public static void prt(int x0, int y0) {
System.out.println("T class ending: x= " + x0 + ", y=" + y0);
}
// <---- this is where an extra statement gets inserted
}
class S extends T {
int m = 10;
int n = m + x + y;
public void prs() {
System.out.println("S subclass ending: m = " + m + ", n=" + n);
}
}
public class A {
public static void main(String[] args) {
System.out.println("****Program start");
System.out.print("main method: ");
T t1 = new T();
t1.prt(3, 4);
S s1 = new S();
System.out.println(s1.m);
System.out.println(s1.n);
s1.prs();
System.out.println("****Program ending");
}
}
However, when I demand to do what Flanagan states is possible, to invoke a class method FROM WITHIN the class T in which the CLASS METHOD is defined, I get the original compilation error again, that "an identifier is expected." That is, inserting the following statement at the end of class T code, as shown above(*), gives a compiLe error:
T.prt(3,4);
Why this is an error? My question asks about general CLASS METHODS, not a special class method, namely a constructor, though the Java reference text I'm citing does deal with CLASS METHODS in general. Am I missing something obvious? My sincerest gratitude, Richard Pan in Newark
That is, inserting the following statement at the end of class T code, as shown above(*), gives a compiLe error:
You can only write code inside methods. Outside methods you can only define fields, which is what it is expecting.
Am I missing something obvious?
I used my IDE to format the code (This was one key press btw) and the problem became obvious. If you don't format your code it make it harder to read and understand.
Give me a situation where we need to use the super class reference to a subclass object in Java.Please give me a real time example.
Thx
I know this is old but this cropped up on a project I've been working on recently (just a junior developer doing something unexpected - there was no actual reason for it!) and I think some of the answers have missed the point..
This has nothing to do with normal polymorphism; I think the question relates to the case where the code looks like this:
class A {
B b; //odd reference here..
}
class B extends A {
}
Where the sub-class is used in the definition of the super-class. As far a I can tell there is no legitimate reason for coding something like this yourself, however the reason the language allows you to do this is that it's required for some of the core Java classes e.g. Object.
For example, although it doesn't store a reference to it, the code for Object creates and returns a String object in it's default toString method, however, String is a sub-class of Object.
It's interesting to note that although it's technically allowed, it doesn't make sense to have a superclass create a subclass instance in its constructor.
e.g.
class A {
B b;
A(){
b = new B();
}
}
class B extends A {
}
This will just crash due to the fact that it creates an infinite loop, since B's constructor is calling A's constructor, which is calling B's constructor etc..
To Take Full Advantage of polymorphism...You have to understand polymorphism fully for you to really appreciate this... You can actually achieve the same behavior using an Interface as appropriate, so they say...
abstract class Shape {
abstract double getArea();
}
class Rectangle extends Shape{
double h, w;
public Rectangle(double h, double w){
this.h = h;
this.w = w;
}
public double getArea(){
return h*w;
}
}
class Circle extends Shape{
double radius;
public Circle(double radius){
this.radius = radius;
}
public double getArea(){
return Math.PI * Math.sqrt(radius);
}
}
class Triangle extends Shape{
double b, h;
public Triangle(double b, double h){
this.b = b;
this.h = h;
}
public double getArea(){
return (b*h)/2;
}
}
public class ShapeT{
public static void main(String args[]){
//USAGE
//Without polymorphism
Triangle t = new Triangle(3, 2);
Circle c = new Circle(3);
Rectangle r = new Rectangle(2,3);
System.out.println(t.getArea());
System.out.println(c.getArea());
System.out.println(r.getArea());
//USAGE with Polymorphism
Shape s[] = new Shape[3];
s[0] = new Triangle(3, 2);
s[1] = new Circle(3);;
s[2] = new Rectangle(2,3);
for(Shape shape:s){
System.out.println(shape.getArea());
}
}
}
I hope I'm not wrong on this... just a thought!
That question doesn't seem quite right ... putting an explicit reference to a child-class in the parent-class seems like an intent to break the hierarchy and the library.
As soon as the parent-class starts to carry a reference to the child-class, the parent-class is dependant upon knowing it's descendants; that is bad.
Unless the question was misquoted here, I'd say your interviewer was talking through his hat.
class Person
String hairColor = "default_noColor";
-----------------------------
class German extends Person
String hairColor = "brown";
-----------------------------
class Scandinavian extends Person
String hairColor = "red";
-----------------------------
public static void main(String args[]) {
Person p = new Person();
German g = new German();
Scandinavian s = new Scandinavian();
sysout p.hairColor // prints default_noColor
if (cond1) {
p = g;
}
sysout p.hairColor // prints brown
else if (cond2) {
p = s;
}
sysout p.hairColor // prints red
}
now, if germans start having black hair, i recompile class German and the main() is totally agnostic of how the German has changed. The main method continues to work as if nothing ever happened and prints black.
Kindly excuse minimal grammar and syntax
Using this kind of assignment you can not call the overloaded method in the subclass which is not in super class.
public class Reference {
public static void main(String args[]){
A a = new B();
//B b = new A(); // You can not do this, compilation error
a.msg(); // calls the subclass method
((B)a).msg("Custom Message"); // You have to type cast to call this
System.out.println(a.getClass());
if(a instanceof B){//true
System.out.println("a is instance of B");
}
if(a instanceof A){//true
System.out.println("a is instance of A also");
}
}
}
class A{
public void msg(){
System.out.println("Message from A");
}
}
class B extends A{
public void msg(){//override
System.out.println("Message from B");
}
public void msg(String msg){//overload
System.out.println(msg);
}
}
Uh, any time? If you have something like a polymorphic linked list:
class Node {
has 'next' => ( isa => 'Node' );
}
class TextNode extends Node {
has 'text' => ( isa => 'Str' );
}
class ImageNode extends Node {
has 'image' => ( isa => 'Image' );
}
Then you can do:
TextNode->new(
text => 'Here is my cat:',
next => ImageNode->new(
image => 'nibbler.jpg',
next => undef,
),
);
Your specific situation involves Node holding a reference to TextNode or ImageNode, which is probably fine in Java:
Node->new( next => TextNode->new ( ... ) )
Though I would make Node a role in languages with that feature... the idea is largely the same.
The Liskov substitution principle states that subclasses should behave exactly like their superclasses, so you can substitute a subclass anywhere the superclass is used.
Here's an important and most instructive example: java.lang.reflect.Array:
The Array class provides static methods to dynamically create and access Java arrays.
getLength(Object array)
Returns the length of the specified array object, as an int.
get(Object array, int index)
Returns the value of the indexed component in the specified array object.
set(Object array, int index, Object value)
Sets the value of the indexed component of the specified array object to the specified new value.
Arrays are passed around as Object, which is the superclass of all array types. It's necessary because we're doing reflection: we don't always know what the array type will be at compile time.
It's really rather odd because the type of situation where it might be useful (supplying a custom implementation of a singleton object for instance) has better alternatives to that; in particular the service loader mechanism.
And outside the world of globals in disguise you do tend to run into issues with circular references. (Consider that the super reference within your sub-class field points to the enclosing super instance which in turn is a reference from within the sub-class ...)
I think this can happen if the class and its subclass share child parent relationship of some sort and the child has a reference to its parent, something like this
public interface Node
{
String getName();
int getValue();
Container getParentContainer();
}
public interface Container extends Node
{
Set<Node> getChildren();
}
I would be interested to see how this can be designed in a better way to resolve this.