I know I can do do the following :
String className = "A";
Object o= Class.forName(className).newInstance();
But consider this case (simplification):
class Parent {
public void action() {...};
}
class A extends Parent {
#Override
public void action() {...};
}
class B extends Parent {
#Override
public void action() {...};
}
class C extends Parent {
#Override
public void action() {...};
}
Now I would like to create a class that can be either of those 3 cases.
If I use the above code and create an Object, I wouldn't be able to call the action method.
I would like to be able to create an object that extends Parent from a string.
In my actuall case I have multiple different parents, and the class is extented from a class that's extended from a class and about 4 layers of inhertiance. Would regular casting work?
Casting would work, but is unnecessary. Class#newInstance() returns an instance of type T, which is the class' generic type. This means that because Class.forName("A") returns an instance of Class<A>, you can declare your instance as Parent due to A's inheritance, as newInstance() is returning an object of type A.
Parent p = Class.forName("A").newInstance();
p.action();
Since all your classes extend Parent you can cast result of newInstance() to this type and then call all methods declared in Parent. The "right" implementation will run.
Parent p = (Parent)Class.forName(className).newInstance();
p.action();
Related
Assign to a variable an object that extends a class and implements an Interface at the same time.
I have a method like this
public static <T extends Component & MyInterface> T instance() {
if (test1) return new MyLabel();
if (test2) return new MyCombo();
if (test3) return new MyText();
}
class MyLabel extends JLabel implements MyInterface {
...
}
class MyCombo extends JComboBox implements MyInterface {
...
}
class MyText extends JTextField implements MyInterface {
...
}
this means the instance() returned object is a Component AND implements MyInterface.
and I can do something like
instance.setEnable(true); // calling a Component method
instance.foo(); // calling a MyInterface method
Now I want to assign the returned value to a variable: how to declare the variable in order to bring with the variable all the Generics info?
I expect to be able to do something like this:
static <T extends Component & MyInterface> T myVar = instance();
myVar.setEnable(true); // calling a Component method
myVar.foo(); // calling a MyInterface method
and also this:
static void f1(Component c) {}
static void f2(MyInterface c) {}
f1(myVar);
f2(myVar);
In my opinion the question is different from the one in Why can't I use a type argument in a type parameter with multiple bounds? because I'm not using a type parameter inside a generic class declaration.
Based on John Bollinger suggestion I do some other experiments and found a possible "solution" (however not as simple as I required).
But I think my wrap() method is different from what John meant.
public final class Wrap<X extends Component & MyInterface> {
public final X x;
public Wrap(X x) {
this.x = x;
}
}
public static <X extends Component & MyInterface> Wrap<X> wrap(X x) {
return new Wrap<X>(x);
}
static Wrap<?> myVar = wrap(instance());
myVar.x.setEnabled(true); // Component method
f1(myVar.x); // Component parameter
myVar.x.foo(); // MyInterface method
f2(myVar.x); // MyInterface parameter
I expect to be able to do something like this:
static <T extends Component & MyInterface> T myVar = instance();
myVar.setEnable(true); // calling a Component method
myVar.foo(); // calling a MyInterface method
I'm afraid not. Java does not offer generic variables, and for the most part it wouldn't make sense to do so. You may declare the type of an instance variable as a type parameter of its class, but you cannot give any variable its own, independent type parameter like you can a method. There is no way to declare a variable that has two types.
If you want to be able to make use of both facets of myVar, as shown in the example, then its type must be declared as a specific type that extends or implements both supertypes. There are two main alternatives for that:
Make the instance() method return such a type. This is probably the most natural solution, since that method doesn't depend on T for any purpose other than to hang supertypes upon.
public class MyInterfaceComponent extends Component implements MyInterface {
// ...
}
MyInterfaceComponent myVar = instance();
Dynamically generate a wrapper object of such a type that adapts general objects that extend the class and implement the interface to a particular type that does so.
MyInterfaceComponent myVar = wrap(instance());
The latter makes sense to me only if there's a possibility that you need to handle externally-provided objects that extend the class and implement the interface, but whose specific class you cannot control.
Consider the code below :
abstract class AbstractClass {
abstract m1();
}
public class Test {
public static void main(String [] args) {
AbstractClass obj = new AbstractClass() {
#Override void m1() {
System.out.print("Instance of abstract class !");
}
};
obj.m1();
}
}
Now here is what I did not understand about this code.
I read that anonymous class creates the class with unknown name which extends the class whose reference is provided (here it is abstract AbstractClass).
Also I remember that we cannot implement the method of child class if the the object is having reference of parent class.
see block of code below
Parent obj = new Child();
obj.methodOfParent();
obj.methodOfChild(); //this gives error
Now here is my point if Anonymous Class extends its Parent Class whose reference is provided, then how can we call overriden methods of Parent Class from Anonymous Class?
I guess you just miss one point. Let me show you example:
class Parent {
public void methodOfParent() {}
public void methodOfParentToBeOverriden() {}
}
class Child extends Parent {
#Override public void methodOfParentToBeOverriden() {}
public void methodOfChild() {}
}
Parent obj = new Child();
obj.methodOfParent(); //this is OK
obj.methodOfParentToBeOverriden(); // this is OK too
obj.methodOfChild(); //this gives error
((Child)obj).methodOfChild(); //this is OK too here.
Please note that when you call obj.methodOfParentToBeOverriden() it will be called implementation from Child class. Independence did you cast this object to Parent type or not.
There is a difference between calling an overridden method of parent and calling a method of child. If a method is declared in class T, you can call it on a variable statically typed as T, regardless of where the method is actually implemented.
In your example, if obj.methodOfParent() happens to be a method override from Child, the method in Child will run, even though obj's static type is Parent.
Same mechanism is in play with anonymous classes: the reason that you are allowed to call obj.m1() is that m1() has been declared in the parent class.
I have an abstract parent class Parent and six child classes ChildA though ChildF.
Another class Other has a six (static) overloaded methods olmeth(), one for each of the six child classes.
How can I write:
Parent message = Factory.returnRandomChildClass();
Other.olmeth(message);
At the moment I use an extra method, overloaded for the parent class, and six instanceof checks to work around this issue. This is unscalable.
How can I get Java to dispatch on the actual type of message, rather on the type of the reference to the message?
Make an abstract method in the Parent, and let each child dispatch to its own static overload:
abstract class Parent {
protected abstract void send();
}
class ChildA extends Parent {
protected void send() {
Other.olmeth(this);
}
}
class ChildB extends Parent {
protected void send() {
Other.olmeth(this);
}
}
...
class ChildF extends Parent {
protected void send() {
Other.olmeth(this);
}
}
Note that although the code in all six implementations of send() look exactly the same, the methods actually dispatch to six different overloads of Other, because the static type of this in each case is different.
Use double dispatch pattern. Implement the olmeth logic for every Parent child class and change your current olmeth method to this:
static void olmeth(Parent p) {
p.olemth();
}
If I have the following class:
public class TestObject {
public String Hooray() {
return "Hooray!";
}
}
I can obviously instantiate the object, and I know some sort of subclassing must be going on since I can override the Hooray method, but if there's subclassing, why can't I create a new method inside the anonymous class?
TestObject a = new TestObject() {
public String Boo() {
return "Booooo";
}
};
System.out.println(a.Boo());
returns a syntax error
You can create the method, there's nothing wrong with your Boo method (apart from the fact that it has a capital letter at the front). The problem is that outside of the anonymous class, the Boo method is not available (it is not exposed as part of the API of the class).
This is the same with any class that implements an interface... if the class has methods (even public methods) that are not part of the interface then you need to cast the instance to the specific class in order to access these methods.
Unfortunately, because this is an anonymous class, you can't cast it (you don't know what to cast it to).
These internal methods can still be useful, but you have to call them from inside the anonymous class, not from outside.
Because the class has no name, you cannot refer to its type definition at compile time. The compiler can only know it as a TestObject, which has no boo() method
You have this:
public class TestObject {
public String Hooray() {
return "Hooray!";
}
}
TestObject a = new TestObject() {
public String Boo() {
return "Booooo";
}
}
System.out.println(a.Boo());
You can't do this. You can create new methods in anonymous inner classes, and, in fact, you are. But you wouldn't be able to call a.Boo() from outside, since a is a TestObject and TestObject has no method named Boo. It's the same reason you can't do this:
public class Base {
public void something ();
}
public class Derived extends Base {
public void another ();
}
Base b = new Derived();
b.another(); // b is a Base, it must be cast to a Derived to call another().
In the above you have to cast b to a Derived to call the new method added to the derived class:
((Derived)b).another();
The reason that you couldn't do this with anonymous inner classes (which are just syntactic shortcuts for deriving new subclasses) is precisely because they are anonymous - there is no type available for you to cast them to.
The reason you can't access another() through type Base, by the way, is pretty simple when you think about it. While Derived is a Base, the compiler has no way of knowing that Base b is holding a Derived as opposed to some other subclass of Base that doesn't have an another() method.
Hope that helps.
I have a parent class which has a method, in the child class I override that parent class's method. In a third class I make an object of child and by using that object I want call the method of parent class. Is it possible to call that parent class method ? If yes, then how?
If you override a parent method in its child, child objects will always use the overridden version. But; you can use the keyword super to call the parent method, inside the body of the child method.
public class PolyTest{
public static void main(String args[]){
new Child().foo();
}
}
class Parent{
public void foo(){
System.out.println("I'm the parent.");
}
}
class Child extends Parent{
#Override
public void foo(){
//super.foo();
System.out.println("I'm the child.");
}
}
This would print:
I'm the child.
Uncomment the commented line and it would print:
I'm the parent.
I'm the child.
You should look for the concept of Polymorphism.
Use the keyword super within the overridden method in the child class to use the parent class method. You can only use the keyword within the overridden method though. The example below will help.
public class Parent {
public int add(int m, int n){
return m+n;
}
}
public class Child extends Parent{
public int add(int m,int n,int o){
return super.add(super.add(m, n),0);
}
}
public class SimpleInheritanceTest {
public static void main(String[] a){
Child child = new Child();
child.add(10, 11);
}
}
The add method in the Child class calls super.add to reuse the addition logic.
First of all, it is a bad design, if you need something like that, it is good idea to refactor, e.g. by renaming the method.
Java allows calling of overriden method using the "super" keyword, but only one level up in the hierarchy, I am not sure, maybe Scala and some other JVM languages support it for any level.
Say the hierarchy is C->B->A with A being the base class.
I think there's more to fixing this than renaming a method. That will work but is that a fix?
One way is to refactor all the functionality common to B and C into D, and let B and C inherit from D: (B,C)->D->A Now the method in B that was hiding A's implementation from C is specific to B and stays there. This allows C to invoke the method in A without any hokery.
NOTE calling parent method via super will only work on parent class,
If your parent is interface, and wants to call the default methods then need to add interfaceName before super like IfscName.super.method();
interface Vehicle {
//Non abstract method
public default void printVehicleTypeName() { //default keyword can be used only in interface.
System.out.println("Vehicle");
}
}
class FordFigo extends FordImpl implements Vehicle, Ford {
#Override
public void printVehicleTypeName() {
System.out.println("Figo");
Vehicle.super.printVehicleTypeName();
}
}
Interface name is needed because same default methods can be available in multiple interface name that this class extends. So explicit call to a method is required.