Need help for Dynamic Method Dispatch Example - java

I need help with this Java Program example. This example is from the book
Java: Seventh Edition by Herbert Schildt.
I have few doubts about this program and also doubts about the text(explanation of this topic) written in this book. This program is written under Inheritance --> Method Overriding. Here A is the super class of B and B is the super class of C. In this program callme() is a method written in the three classes where each callme() overides another callme() method.
1) In the program below, what does obtain a reference of type A means? (This concept is implemented in the line A r; in the Main method)
2) What is name space convention?
3) In this program, what does "r referes to an A object mean"? (This concept is implemented in the lines r.callme(); written in the main method.)
class A
{
void callme()
{
System.out.println("Im in the class A");
}
}
class B extends A
{
void callme()
{
System.out.println("Im in the class B");
}
}
class C extends B
{
void callme()
{
System.out.println("Im in the class C");
}
}
public class Dispatch
{
public static void main(String args[])
{
A a = new A();
B b = new B();
C c = new C();
A r;
r = a;
r.callme();
r = b;
r.callme();
r = c;
r.callme();
}
}

This is a way to overcome the problem of method over-riding.
If you want to get rid of method over-ridden at some time during your development then you can use this way of DMD.
Referring your example with comments:
class A //Super class A
{
void callme() // method callme() that'll be overwritten next in subclasses
{
System.out.println("Im in the class A");
}
}
class B extends A //Subclass B inherited from A
{
void callme() //method callme() of Super class A is over-hided here
{
System.out.println("Im in the class B");
}
}
class C extends B //Subclass C, inherited from B
{
void callme() // this time B subclass method callme() is over-hided
{
System.out.println("Im in the class C");
}
}
//Now suppose, during you development phase at some time, you don't want to use over-ridden methods, here is DMD to help you out at run time.
public class Dispatch
{
public static void main(String args[])
{
A a = new A();
B b = new B();
C c = new C();
A r;
// r is a reference to class A
// this reference should be assigned to each type of object and called at
// run time without compiling.
r = a;
r.callme();
r = b; r.callme();
r = c; r.callme();
}
}

Related

How to write a class to restrict object creation to once in case of multilevel inheritance?

Suppose we have three classes A,B and C
class A{
A(){
System.out.println("A");
}
}
class B extends A{
B(){
//super
System.out.println("B");
}
}
class C extends B{
C(){
//super
System.out.println("C");
}
}
public class Main{
public static void main(String[] args){
C c = new C(); // This will print ABC and that is fine
C c' = new C(); // Should not be allowed
}
}
I want to put some logic so that C c' = new C() should not be allowed after creation of c. Any suggestions would be highly appreciated. I was asked this question in interview and interviewer threw a hint saying " You can do something with super ". But I failed to answer.
It looks like you want the singleton pattern.
class C extends B {
private static class SingletonHolder {
static final C SINGLETON = new C();
}
private C() {
super();
System.out.print("C");
}
public static C getInstance() {
return SingletonHolder.SINGLETON;
}
}
This way, it will only print ABC once, the first time getInstance is called, because SingletonHolder will only be loaded when you call getInstance.
You can then use it like this:
C c = C.getInstance();
If you instead want a runtime exception, then you can keep a static boolean field in C telling if C's constructor has already been called, and throw an exception if someone tries to instantiate it again. However, I doubt that's what the interviewer was looking for.

Java Function Call with Overload [duplicate]

This question already has answers here:
Method overloading using derived types as parameters in Java
(3 answers)
Closed 4 years ago.
I want to know why the third output is NOT b.
Here is my code:
public class SimpleTests {
public void func(A a) {
System.out.println("Hi A");
}
public void func(B b) {
System.out.println("Hi B");
}
public static void main(String[] args) {
A a = new A();
B b = new B();
A c = new B();
SimpleTests i = new SimpleTests();
i.func(a);
i.func(b);
i.func(c);
}
}
class A {}
class B extends A {}
And here is the output:
Hi A
Hi B
Hi A
Could someone tell me why the 3rd output is Hi A, NOT Hi B. as the real c is a instance of B.
You're confusing overloading with polymorphism.
With polymorphism, when creating an instance of class B which is a subclass of class A, referenced to by an class A object, and overwrites the method of class A, calling the method will perform the method of class B.
With overloading, the called method only knows the type of the declaration of the argument, not the initialization.
public class A {
public void print() {
System.out.println("A");
}
}
public class B extends A {
#Override
public void print() {
System.out.println("B");
}
}
public class Main {
public static void main(String[] args) {
A a = new A();
B b = new B();
A otherB = new B();
a.print();
b.print();
otherB.print();
}
}
This will output
A
B
B
Calls to overloaded methods are resolved based on the reference type (A) of the argument at compile time, not the object type (B) at runtime. You declared the variable to be of type A, so it is treated as type A.
JLS ยง8.4.9. Overloading:
When a method is invoked, the number of actual arguments (and any
explicit type arguments) and the compile-time types of the arguments
are used, at compile time, to determine the signature of the method
that will be invoked.
The compile-time types in your example are:
A a = new A(); // A
^
B b = new B(); // B
^
A c = new B(); // A
^
Therefore, the output is:
Hi A
Hi B
Hi A

why in nested interface loop we need not be give implemented method higher access privilege?

interface a {
interface b {
void m();
}
}
class c implements a.b {
void m() {
System.out.println("hello1");
}
}
class d extends c {
public static void main(String[] args) {
c v = new c();
v.m();
}
}
in this example, it shows assign weaker privilege but instead of implementing a.b , I implemented only a then it will give the output why is this happen ,what is the reason behind it??
interface a {
interface b {
void m();
}
}
class c implements a {
void m() {
System.out.println("hello1");
}
}
class d extends c {
public static void main(String[] args) {
c v = new c();
v.m();
}
}
op "hello1"
Because you are NOT implementing the a.b interface method m explicitly for class c.
In your first example, when you call v.m, m is being called against an instance of c directly.
Because you have an m method in c, the compiler is happy that you have implemented interface b for class c
In your second example, you are still calling v on c, but because a is an empty interface with no members defined, only a child interface, the compiler is happy again.

Java: create dynamic Object instance based on the Generic Type [duplicate]

This question already has answers here:
How do I get a class instance of generic type T?
(23 answers)
Closed 6 years ago.
I want to use the polymorphism in Java in way to handle the following scenario:
public class Main {
public static void main (String[] args) {
handle(new B());
handle(new C());
}
public static void handle(A a){
// here I want to create a F<T>, in way that:
// * F must be C or D if A is B or C
// * T must B the real type of A
// e.e:
// new F<A>();
// task => see the output from D or E
}
}
class A {
}
class B extends A {
}
class C extends A {
}
class D<B> extends F{
public D(){
System.out.println("Created D of B");
}
}
class E<C> extends F{
public E(){
System.out.println("Created E of C");
}
}
abstract class F<T>{
}
The entry point is the handle method of the class Main.
The method receive an object A, that can be an instance of the class B or C.
My task is to find a way to create a new Object F that depends on the real Type of the A instance received, and the F object must be C or D depending on A, if it's B or C respectively.
Any idea will be appreciated.
Thanks.
#See Java type-erasure concepts. doc
One of the things you can do is to introduce virtual method in A:
F<? extends A> supply();
So, with the help of polymorphism you will delegate instantiation to the concrete class. This approach is similar to Template method pattern.
you can check if a is an instance of B or C using instanceof keyword, this is probably the handle method implementation your are looking for (more or less):
public static F handle(A a){
if (a instanceof B) {
// a is B, do something about that, possibly create some D<B> ?
return new D();
}
if (a instanceof C) {
// a is C, do something about that, possibly create some E<C> ?
return new E();
}
// if somehow you get here, that means something weird happened
throw new RuntimeException("unsupported case");
}
I have solved with this implementation:
public class Main {
private static D d;
public static void main (String[] args) {
handle(new B());
handle(new C());
}
public static void handle(A a){
d = solveD(a);
d.handle(a);
}
private static D solveD(A a){
if (a instanceof B){
return new E();
} else return new F();
}
}
class A {
}
class B extends A {
}
class C extends A {
}
interface D<T extends A>{
public void handle(T t);
}
class E implements D<B> {
#Override
public void handle(B b){
System.out.println("Handling E of B");
}
}
class F implements D<C>{
#Override
public void handle(C c){
System.out.println("Handling F of C");
}
}
Using Spring, it's not necessary the method solveD, because we can get the bean based on the a.getClass().getSimpleName(), annotating E and F with #Component.

(Java) Difference ways of instantiating subclasses

I have these two classes:
public class A {}
public class B extends A {}
In the main class, I would declare:
A a = new B();
B b = new B();
What is the difference between a and b ? Is this what we called a subtyping in java?
The difference between a and b is that with a you can only use the public API that the A class provides even though its really a B type object, but with b, you can use both the A's public API as well as B's public API.
For example:
Suppose A and B are defined as follows:
// A.java
public class A
{
public void x()
{
z("X");
}
public void y()
{
z("Y");
}
protected void z(String message)
{
System.out.println(message);
}
}
// B.java
public class B extends A
{
public void a()
{
z("A");
}
public void b()
{
z("B");
}
}
And here's a demo:
// Demo.java
public class Demo
{
public static void main(String[] args)
{
A a = new B();
B b = new B();
// Can only call A's public methods
a.x();
a.y();
// a.a(); Can't use
// a.b(); Can't use
// Can call all public methods
b.a();
b.b();
b.x();
b.y();
}
}
Yes, there is difference between them. Accssibility of methods are different depends on what kind of reference you use.
A a = new B();
B b = new B();
a is a reference of Class A and b is a reference of class B. super class always can be used to point subclass object.
reference a able to access only super class method and properties
reference b able to access super class and it's own method and properties
one important thing is, ability of accessibility of function and properties will decided at runtime.
In below two cases
A a = new B();
a is an instantiation of B and of type A.
whereas in
B a = new B();
a is an instantiation of B and of type B.
The important thing to note here is that (in the first case) if you call a.someMethod(), the method of B will be called, not the method of A (this is called dynamic binding, as opposed to static binding).
This is basic inheritance. In the B b = ... case you can access all methods and variables provided from A and B but in the A case you can only use the methods and variables in the A case.
B gets typecasted into A when it is created, but that information is not required by the compiler.
public class A {
int x;
}
public class B extends A {
int y;
}
A a = new B();
B b = new B();
int c = a.x; //works
int c = a.y; //doesn't work
int c = b.y; //works
int c = b.x; //works
Remember, that you can always cast an object "downwards" in the inheritance chain. But you should not cast a object upwards because the variables for the subclass might be used even though they dont exist, for exmaple B b = new A(); So b.y is dangerous since the B object doesn't have an y variable defined.

Categories

Resources