Java: initialization and costructor of anonymous classes - java

I would like to understand a strange behavior I faced dealing with anonymous classes.
I have a class that calls a protected method inside its constructor (I know, poor design but that's another story...)
public class A {
public A() {
init();
}
protected void init() {}
}
then I have another class that extends A and overrides init().
public class B extends A {
int value;
public B(int i) {
value = i;
}
protected void init() {
System.out.println("value="+value);
}
}
If I code
B b = new B(10);
I get
> value=0
and that's expected because the constructor of the super class is invoked before the B ctor and then value is still.
But when using an anonymous class like this
class C {
public static void main (String[] args) {
final int avalue = Integer.parsetInt(args[0]);
A a = new A() {
void init() { System.out.println("value="+avalue); }
}
}
}
I would expect to get value=0 because this should be more or less equal to class B: the compiler automatically creates a new class C$1 that extends A and creates instance variables to store local variables referenced in the methods of the anonymous class, simulating a closure etc...
But when you run this, I got
> java -cp . C 42
> value=42
Initially I was thinking that this was due to the fact that I was using java 8, and maybe, when introducing lamdbas, they changed the way anonymous classes are implemented under the hood (you no longer need for final), but I tried with java 7 also and got the same result...
Actually, looking at the byte code with javap, I can see that B is
> javap -c B
Compiled from "B.java"
public class B extends A {
int value;
public B(int);
Code:
0: aload_0
1: invokespecial #1 // Method A."<init>":()V
4: aload_0
5: iload_1
6: putfield #2 // Field value:I
9: return
...
while for C$1:
> javap -c C\$1
Compiled from "C.java"
final class C$1 extends A {
final int val$v;
C$1(int);
Code:
0: aload_0
1: iload_1
2: putfield #1 // Field val$v:I
5: aload_0
6: invokespecial #2 // Method A."<init>":()V
9: return
....
Could someone tell me why this difference?
Is there a way to replicate the behavior of the anonymous class using "normal" classes?
EDIT:
to clarify the question: why does the initialization of the anonymous classes break the rules for initializing of any other class (where super constructor is invoked before setting any other variable)?
Or, is there a way to set instance variable in B class before inovking super constructor?

This question applies to all inner classes, not just anon classes. (Anon classes are inner classes)
JLS does not dictates how an inner class body accesses outer local variable; it only specifies that the local variables are effectively final, and definitely assigned before the inner class body. Therefore, it stands to reason that the inner class must see the definitely assigned value of the local variable.
JLS does not specify exactly how the inner class sees that value; it is up to the compiler to use whatever trick (that is possible on the bytecode level) to achieve that effect. In particular, this issue is completely unrelated to constructors (as far as the language is concerned).
A similar issue is how an inner class accesses the outer instance. This is a bit more complicated, and it does have something to do with constructors. Nevertheless, JLS still does not dictate how it is achieved by the compiler; the section contains a comment that "... compiler can represent the immediately enclosing instance how ever it wishes. There is no need for the Java programming language to ... "
From JMM point of view, this under-specification might be a problem; it is unclear how writes were done in relation to reads in inner class. It is reasonable to assume that, a write is done on a synthetic variable, which is before (in programming order) the new InnerClass() action; the inner class reads the synthetic variable to see the outer local variable or the enclosing instance.
Is there a way to replicate the behavior of the anonymous class using "normal" classes?
You may arrange the "normal" class as outer-inner class
public class B0
{
int value;
public B0(int i){ value=i; }
public class B extends A
{
protected void init()
{
System.out.println("value="+value);
}
}
}
It will be used like this, which prints 10
new B0(10).new B();
A convenience factory method can be added to hide the syntax ugliness
newB(10);
public static B0.B newB(int arg){ return new B0(arg).new B(); }
So we split our class into 2 parts; the outer part is executed even before the super constructor. This is useful in some cases. (another example)
( inner anonymous access local variable enclosing instance effective final super constructor)

Your anonymous class instance behaves differently than your first code snippet since you are using a local variable whose value is initialized before the anonymous class instance is created.
You can get a similar behavior to the first snippet with an anonymous class instance if you use an instance variable in the anonymous class :
class C {
public static void main (String[] args) {
A a = new A() {
int avalue = 10;
void init() { System.out.println("value="+avalue); }
}
}
}
This will print
value=0
since init() is executed by A's constructor before avalue is initialized.

The variable capture in anonymous classes is allowed to break the rules of normal constructors (super constructor call must be the first statement) because this law is only enforced by the compiler. The JVM allows any bytecode to be ran before invoking the super constructor, which is utilized by the compiler itself (it breaks it's own rules!) for anonymous classes.
You can mimic the behavior either with inner classes as shown in bayou.io's answer, or you can use an anonymous in a static B factory method:
public class B extends A
{
public static B create(int value)
{
return new B() {
void init() { System.out.println("value="+value);
};
}
}
The limitation is actually rather pointless and can be annoying in some situations:
class A
{
private int len;
public A(String s)
{
this.len = s.length();
}
}
class B extends A
{
private String complexString;
public B(int i, double d)
{
super(computeComplexString(i, d));
this.complexString = computeComplexString(i, d);
}
private static String computeComplexString(int i, double d)
{
// some code that takes a long time
}
}
In this example, you have to do the computeComplexString computation twice, because there is no way to both pass it to the super constructor and store it in an instance variable.

The two examples are not related.
In the B example:
protected void init() {
System.out.println("value="+value);
}
the value being printed is the value field of the instance of B.
In the anonymous example:
final int avalue = Integer.parsetInt(args[0]);
A a = new A() {
void init() { System.out.println("value="+avalue); }
}
the value being printed is the local variable avalue of the main() method.

Related

OOP - inheritance [Java]

bb refers Derived class, when i call show() method, but when i print bb.b - is prints Base class property .
Why is this happening?
class Base {
int b=10;
public void show() {
System.out.println("Base show() called");
}
}
class Derived extends Base {
int b=20;
public void show() {
System.out.println("Derived show() called");
}
}
public class MainClass {
public static void main(String[] args) {
Base bb = new Derived();;
bb.show();
System.out.println(bb.b);
}
}
output :
Derived show() called
10
While you declare your variable as a Base obj (i.e. Base bb = new Derived();), that does not mean your b object is no longer an instance of Derived (verify this with b instanceof Derived).
This is called hiding and is similar to what people usually do when declaring variables that might later change implementation for example private List<String> someList = new ArrayList<>();. In more technical terms: it's a way of decoupling your code from a specific implementation.
As to why b is 10 (the Base class's value) and not 20: that is because you are explicitly referring to b value in Base class (as mentioned by Timothy Truckle's answer). If you were to explicitly cast your b object back to Derived type, you will see 20 being printed instead:
System.out.println(((Derived)b).b);
You output is 10because you explicitly access variable b in class Base.
Beside the technical aspect doing so this is not OOP since it violates the most important OO principle: information hiding / encapsulation.
This is because the compiler implements special run time polymorphism for methods only. This is also called method overriding.
For variables, the value will always be from the Base class, because that is the type of bb object regardless of the class with with it is instantiated.
There is no polymorphism for fields in Java.
Variables are resolved compile-time, methods run-time. so always Base Class variables (not child’s inherited variables) will be accessed.
So whenever upcasting happens always remember
Base Class variables will be accessed.
Sub Class methods(overridden methods if overriding happened else inherited methods as it is from parent) will be called.

Why can't a local class that extends an inner class access the inner class enclosing instance?

(I keep re-reading that question title and thinking about how ridiculous it must look, but I assure you that is the best description of the problem, and I have an actual application where this is the best structure. I swear I'm not crazy.)
Consider the following. Each block is a separate file:
package myPackage;
public class A {
public int i;
public A(int i) {
this.i = i;
}
public class B {
}
}
package myPackage;
import myPackage.A.B;
public class Main {
public static void main(String[] args) {
class C extends B {
public C(A enclosingInstance) {
enclosingInstance.super();
}
public void show() {
System.out.println(A.this.i);
}
}
A myA = new A(2);
C myC = new C(myA);
myC.show();
}
}
Note that the enclosingInstance business is to solve a problem involving intermediate constructor invocations. See "Why can't outer classes extend inner classes?".
I would expect the output to be "2". But instead, I have a compile error on System.out.println(A.this.i);:
No enclosing instance of the type A is accessible in scope
I think the programmatic concept I'm trying to solve is sound: Create a new type of B inside main to give to A that uses things from A that types of B can access.
So what am I doing wrong, or why isn't this possible in java?
EDIT/UPDATE: Note that the same error appears when the code in main is moved to a non-static method. That is to say, I tried moving everything inside of static void main to a new, non-static method of class Main called go(). Then I changed static void main to the single line new Main().go();. The error is in the same spot. So it doesn't seem to be an issue of class C being defined in a static context.
You want A.this to refer to the enclosing instance of the B instance. But why should it? That's not what the syntax means. A.this would mean the enclosing A instance of the C instance, and this does not make sense because C is not an inner class of A.
To make this clearer, here is an example where C is an inner class of A.
public class A {
public int i;
public A(int i) {
this.i = i;
}
public class B {
void foo() {
System.out.println(A.this.i);
}
}
public class C extends B {
C(A a) {
a.super();
}
void bar() {
System.out.println(A.this.i);
}
}
public static void main(String[] args) {
A a1 = new A(1);
A a2 = new A(2);
C c = a1.new C(a2);
c.foo();
c.bar();
}
}
Here C extends B, and both C and B are inner classes of A. Therefore any C has an enclosing A instance, and it also has an enclosing A instance when considered as a B, and these enclosing instances are different (as proved by the fact that foo and bar print different numbers).
So, A.this could not possibly mean what you want it to mean, because it already means something else. I guess the reason why the language designers didn't come up with other syntax to mean the enclosing instance of a super class, is because such syntax would be very complicated, with little pay-off (simple workarounds already exist).
This is absurd code that you should never write for production.
It is, in part, explained in the documentation for Explicit Constructor Invocations
Qualified superclass constructor invocations begin with a Primary
expression or an ExpressionName. They allow a subclass constructor to
explicitly specify the newly created object's immediately enclosing
instance with respect to the direct superclass (§8.1.3). This may be
necessary when the superclass is an inner class.
All this to say that C is a local class (which is an inner class, which is kind of nonsense because if you declare it in a static method there is no enclosing instance) that is a subclass of B but not a nested class of A. As such, there is no enclosing instance. An instance of C does not have an enclosing instance. (Though it would if you declared it in an instance method, but that would be an instance of Main.)
The newly created object's immediately enclosing instance (from JLS) is specified indirectly through a constructor parameter.
You'd have to store it yourself
private A enclosingInstance;
public C(A enclosingInstance) throws CloneNotSupportedException {
enclosingInstance.super();
this.enclosingInstance = enclosingInstance;
}
and since A#i is public, you can access it normally
public void show() {
System.out.println(enclosingInstance.i);
}
With the provided information, I would do this :
public class B {
protected A getOuterInstance() {
return A.this;
}
}
and just let C inherit and use this method. I know you dislike this method but this is the simplest answer I can see. With more information, I would probably propose a design which would try not involving any inner class as this is not a normal use case for inner classes.

Inheritance and constructors in Java

In the following example:
class A {
private int a;
private int b;
private int c;
public A(int a, int b , int c) {
this.a = a;
this.b = b;
this.c = c;
}
}
class B extends A {
public B() {
super(1,2,3);
}
Does the statement super(1,2,3) in the class B create a private fields same as the private fields in the class A? Or is it illegal to use this statement because B cant inherit the private fields of A?
And we suppose that we didn't use the super constructor in the class B then normally the computer will call the default constructor of the class A. We know that private fields are not inherited in Java so what will the default constructor initialize in this state ?
You cannot call super() like this:
class B extends A {
super(1,2,3);
}
super() OR this() should be the first statement in a constructor. First correct this basic mistake of yours before going further. super() is used by default even if you don't explicitly use it.
class B extends A {
B (){
super(1,2,3);
}
}
This is the right way. Please Read about Constructors and Java language basics first before posting questions.
EDIT
I didn't notice that someone edited you question to add super(1,2,3) in a constructor, now answering your questions as follows:
Does the statement super(1,2,3) in the class B create a private fields same as the private fields in the class A? Or is it illegal to use this statement because B cant inherit the private fields of A?
No, by calling super(1,2,3) all you're doing is passing 3 integer values to the base class constructor public A(int a, int b , int c) After that you're assigning these values to the private instance variables of base class, you're not making a separate fields for class B, if thats what you asked, and No B class still can't access base class instance variables directly (by stating directly I mean by inheritance or making an instance, there are other ways like setters/getters etc)
And we suppose that we didn't use the super constructor in the class B then normally the computer will call the default constructor of the class A. We know that private fields are not inherited in Java so what will the default constructor initialize in this state ?
No, if you don't use a constructor in B class which uses super(int, int, int) to match the arguments of base class constructor (int a, int b , int c) then your code won't even compile. The default constructor will call the no-args constructor of Base class, but since Base class has no default constructor you'll get compilation error!
First of all, the code you posted is not valid Java. It is important that you post working code, otherwise we can't be sure about what you are asking.
Does the statement super(1,2,3) in the class B create a private fields same as the private fields in the class A? Or is it illegal to use this statement because B cant inherit the private fields of A?
Assuming you put the statement in a constructor instead of at class level, which is illegal, then no, that will not automatically create fields in class B. It just calls the constructor in the superclass A that takes three int arguments and initializes the fields in the superclass part of the object.
And we suppose that we didn't use the super constructor in the class B then normally the computer will call the default constructor of the class A. We know that private fields are not inherited in Java so what will the default constructor initialize in this state ?
Since there is no default (i.e. no-arguments) constructor in class A, you would get a compiler error - the compiler would complain that there is no appropriate constructor in class A.
Java only automatically adds a no-arguments constructor to a class if you do not specify a constructor at all in the class. Since class A already has a constructor, Java is not automatically going to add a no-arguments constructor.
First of all you need to understand one thing: private fields of a parent class ARE BEING INHERITED. The only thing is that if they are private in parent, then they cannot be accessed directly from the child class (the B class in your example). So in other words: not a single B class method can access those fields, but every A class method can access them. So for example its possible that there is a public/protected method inside A class that changes some of those fields and this method can be called from a child class (B).
Once you correct your class to the proper:
class B extends A {
public B() {
super(1,2,3);
}
}
...we can proceed to answer your actual questions.
The constructor of A does not create fields. The fields are created as part of creating of any A object, and are initialized by the constructor.
Those fields are created in B as well, but not because you called super(1,2,3) but because you extend A. As soon as an instance of B, which is an extended instance of A is created, those fields are there - but they are accessible only to methods that are declared in A itself and not in its descendents.
By calling super(1,2,3), you are initializing those private fields. They are still not accessible to B. The constructor of A is mediating between B and these private variables. If you had a method that prints those fields in A, and that method was not private, you could call it and it would print them with these values.
As for your second question, if you didn't call the super(1,2,3), Java would try to call the default constructor. However, for a class that has a constructor, there is no default constructor. The empty/nullary constructor only exists if you either declared it yourself, or if you didn't declare any constructor at all.
// The following two classes have a default constructor which will be called
// if any descendent doesn't call super(...)
class HasADefaultConstructor {
}
class AlsoHasADefaultConstructor {
AlsoHasADefaultConstructor() {
}
}
// But this one doesn't.
class DoesntHaveADefaultConstructor {
DoesntHaveADefaultConstructor( String a ) {
}
}
So you can't inherit private varibles, but you can access them if the parent class has the appropriate getters:
Run the example and you see the output is 'a is: 1'
Regarding the default constructor: In your example you have explicitly implemented
a constructor. So the implicit default constructor is not there any more
class B extends A {
public B() {
super(1, 2, 3);
}
public void foo() {
System.out.println("a is: " + super.getA());
}
public static void main(String[] args) {
B bb = new B();
bb.foo();
}
}
class B extends A {
public B() {
super(1, 2, 3);
}
public void foo() {
//access a
System.out.println("a is: " + super.getA());
}
public static void main(String[] args) {
B bb = new B();
bb.foo();
}
}

Why do extensions of inner classes get duplicate outer class references?

I have the following Java file:
class Outer {
class Inner { public int foo; }
class InnerChild extends Inner {}
}
I compiled then disassembled the file using this command:
javac test.java && javap -p -c Outer Outer.Inner Outer.InnerChild
This is the output:
Compiled from "test.java"
class Outer {
Outer();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
}
Compiled from "test.java"
class Outer$Inner {
public int foo;
final Outer this$0;
Outer$Inner(Outer);
Code:
0: aload_0
1: aload_1
2: putfield #1 // Field this$0:LOuter;
5: aload_0
6: invokespecial #2 // Method java/lang/Object."<init>":()V
9: return
}
Compiled from "test.java"
class Outer$InnerChild extends Outer$Inner {
final Outer this$0;
Outer$InnerChild(Outer);
Code:
0: aload_0
1: aload_1
2: putfield #1 // Field this$0:LOuter;
5: aload_0
6: aload_1
7: invokespecial #2 // Method Outer$Inner."<init>":(LOuter;)V
10: return
}
The first inner class has its this$0 field, pointing to the instance of Outer. That's fine. The second inner class, which extends the first, has a duplicate field of the same name, which it initializes before calling the super class's constructor with the same value.
The purpose of the int foo field above is just to confirm that inherited fields from the superclass do not show up in the javap output of a child class's dissassembly.
The first this$0 field is not private, so InnerChild should be able to use it. The extra field just seems to waste memory. (I first discovered it using a memory analysis tool.) What is its purpose and is there a way I can get rid of it?
The two classes may not be inner classes of the same class (if you had a complex hierarchy), so there does exist cases where the two references would be different.
For example:
class Outer {
class InnerOne {
}
class Wrapper {
class InnerTwo extends InnerOne {
}
}
}
InnerTwo has a reference to Wrapper, InnerOne has a reference to Outer.
You can try it with the following Java code:
public class Main{
static class Outer {
class InnerOne {
String getOuters() {
return this+"->"+Outer.this;
}
}
class Wrapper {
class InnerTwo extends InnerOne {
String getOuters() {
return this+"->"+Wrapper.this+"->"+super.getOuters();
}
}
}
}
public static void main(String[] args){
Outer o = new Outer();
Outer.Wrapper w = o.new Wrapper();
Outer.Wrapper.InnerTwo i2 = w.new InnerTwo();
System.out.println(w);
System.out.println(i2);
System.out.println(i2.getOuters());
}
}
I've set it up as a snippet on tryjava8: http://www.tryjava8.com/app/snippets/52c23585e4b00bdc99e8a96c
Main$Outer$Wrapper#1448139f
Main$Outer$Wrapper$InnerTwo#1f7f1d70
Main$Outer$Wrapper$InnerTwo#1f7f1d70->Main$Outer$Wrapper#1448139f->Main$Outer$Wrapper$InnerTwo#1f7f1d70->Main$Outer#6945af95
You can see that the two getOuters() calls are referencing a different object.
#TimB's answer is interesting because it shows how subtle the outer class references can be, but I think I've found a simpler case:
class Outer {
class Inner {}
}
class OuterChild extends Outer {
class InnerChild extends Inner {}
}
In this case, InnerChild's this$0 reference is of type Child rather than Outer, so it can't use the this$0 field from its parent because even though the value is identical, it's the wrong type. I suspect this is the origin of the extra field. Still, I believe Javac could eliminate it when InnerChild and Inner have the same outer class, because then the field has the same value and the same type. (I would report it as a bug but they never fix them, and if it's not a bug they don't give feedback anyway.)
I've finally figured out some decent workarounds though.
The plainest workaround (which took me far too long to think of) is to make the member classes "static", and store the ref to Outer as an explicit field on the base class:
class Outer {
static class Inner {
protected final Outer outer;
Inner(Outer outer) {
this.outer = outer;
}
}
static class InnerChild extends Inner {
InnerChild(Outer outer) {
super(outer);
}
}
}
Through the outer field, both Inner and InnerChild can access instance members of Outer (even private ones). This is equivalent to the code that I think Javac should generate anyway for the original non-static classes.
Second workaround: I discovered by complete accident that the child class of a non-static member class may be static! All these years in Java I never knew about the obscure syntax which makes this work... it is not in the official tutorials. I would have always believed it impossible except that Eclipse automatically filled in the constructor for me. (However, Eclipse doesn't seem to want to repeat this magic... I'm so confused.) Anyway, apparently it's called a "qualified superclass constructor invocation", and it's buried in the JLS in section 8.8.7.1.
class Outer {
class Inner {
protected final Outer outer() { return Outer.this; }
}
static class InnerChild extends Inner {
InnerChild(Outer outer) {
outer.super(); // wow!
}
}
}
This is very similar to the previous workaround, except Inner is a instance class. InnerChild avoids the duplicate this$0 field because it's static. Inner provides a getter so that InnerChild can access the ref to Outer (if it wants to). This getter is final and non-virtual, so is trivial for the VM to inline.
A third workaround possibility is to store the outer class ref only in InnerChild, and let Inner access it through a virtual method:
class Outer {
static abstract class Inner {
protected abstract Outer outer();
}
class InnerChild extends Inner {
#Override protected Outer outer() { return Outer.this; }
}
}
This is probably less useful(?). One advantage is it lets InnerChild have a simpler constructor invocation, since the ref to its enclosing class will usually be passed to it implicitly. It might also be an obscure optimization if InnerChild has a different enclosing class (OuterChild, extending Outer), which it needs to access members of more often than Inner needs to access members of Outer -- it lets InnerChild use members of OuterChild without casting, but requires Inner to invoke a virtual method to access members of Outer.
In practice, all these workarounds are a bit of a nuisance, so they're only worth it if you have many thousands of instances of classes like this (which I do!).
Update!
Just realized the "qualified superclass constructor invocation" is a big piece of the puzzle as to why Javac generates duplicate fields in the first place. It is possible for an instance of InnerChild, extending Inner, both member classes of Outer, to have a different enclosing instance to what its superclass considers to be the enclosing instance:
class Outer {
class Inner {
Inner() {
System.out.println("Inner's Outer: " + Outer.this);
}
}
class InnerChild extends Inner {
InnerChild() {
(new Outer()).super();
System.out.println("InnerChild's Outer: " + Outer.this);
}
}
}
class Main {
public static void main(String[] args) {
new Outer().new InnerChild();
}
}
Output:
Inner's Outer: Outer#1820dda
InnerChild's Outer: Outer#15b7986
I still think that with some effort, Javac could eliminate the duplicate field in the common case, but I'm not sure. It's certainly a more complex problem than I first thought.

Confusion in Java polymorphism

I am having confusion in java polymorphism. In dynamic method binding jvm decides at run time which class method has to call. Suppose I am having three classes A, B and C.
class A{
int get(){
return 10;
}
int getParent(){
return 10;
}
}
class B extends A
{
int get(){
return 20;
}
}
public class C
{
public static void main(String args[])
{
A a = new A();
A a1 = new B();
System.out.println(a.get());/////////////////////////LINE1
System.out.println(a1.get ());////////////////////////LINE2
System.out.println(a.getParent());////////////////////////LINE3
}
}
I am having confusion in line 1 and line3 at compile time and runtime binding.
In line 3 it a.getParent() and this method is in parent class only so what it has to decide at runtime.
In line 1 both reference and object are from same class so again what it has to decide .
Please send me any good link for runtime and compile time binding how works.
class A
{
public doIt( )
{
//this does something
}
}
class B extends A
{
public doIt( )
{
//this does something
}
}
class C extends B
{
public doIt( )
{
//this does something
}
}
public static void main(String[] args) {
A x = new B( );
x.doIt( );
}
The statement that causes a lot of confusion is the “A x = new B();” statement. Although the variable x is an object of type A, it is instantiated as an object of class B – because of the “= new B( );” part of the statement. The Java runtime will basically look at this statement and say “even though x is clearly declared as type A, it is instantiated as an object of class B, so I will run the version of the doIt() method that is defined in class B.”
The version of the doIt() method that’s executed by the object x is the one in class B because of what is known as dynamic binding in Java – the code above can be considered to be an example of dynamic binding. Dynamic binding basically means that the method implementation that is actually called is determined at run-time, and not at compile-time. And that’s why it’s called dynamic binding – because the method that will be run is chosen at run time. Dynamic binding is also known as late binding.
In early binding the data and method are binds at the complie time where as in
late binding the data and method will bind at the runtime.
Class B overrides the get() method. So whenever you call get() on an object that is of type B it will use the overridden method.
Because B doesnt override getparent(), then the parent getParent() will be called when you call it on class B
Class A provides the Object instance a with a virtual method table, containing A.get and A.getParent.
Class B provides the Object instance a1 with a virtual method table, being first taken from class A, and expanded (here nothing to expand with). The get method is overwritten with B.get.
a1.get, even being a A, will call B.get.
polymorphism here applies only in the case of line2. There is no concept of polymorphism applied to line1 and line3.

Categories