java polymorphism creating a new subclass object using a superclass variable - java

I want to create a new instance depending on an object, where I have the super class variable. Is this somehow possible without implementing a getNew() function or without usage of an ugly if chain?
In other words: How to implement the following newSubClass(..) function without using the getNew() function?
public abstract class SuperClass {
abstract public SuperClass getNew();
}
public class SubClassA extends SuperClass {
#Override
public SuperClass getNew() {
return new SubClassA();
}
}
public class SubClassB extends SuperClass {
#Override
public SuperClass getNew() {
return new SubClassB();
}
}
private SuperClass newSubClass(SuperClass superClass) {
return superClass.getNew();
}

After having some time to think about and zv3dh's contribution I decided this second answer.
I'am getting now you want an new instance of an instance of a subclass' type of SuperClass without knowing the concrete sub-type at runtime.
For that you have "reflexion".
public abstract class A_SuperClass {
public A_SuperClass createNewFromSubclassType(A_SuperClass toCreateNewFrom) {
A_SuperClass result = null;
if (toCreateNewFrom != null) {
result = toCreateNewFrom.getClass().newInstance();
}
// just an example, add try .. catch and further detailed checks
return result;
}
}
public class SubClassA extends A_SuperClass {
}
public class SubClassB extends A_SuperClass {
}
If you search for "java reflexion" you will get lots of results here on SO and on the web.

Have a look at the "FactoryMethod" design pattern.
It is exactly what you are looking for: It does encapsulate the "new" operator.
However your example makes me wonder:
Your getNew() reimplements what the constructor would do anyway
Try something like this:
public abstract class SuperClass {
public SuperClass createSuperClass(object someParam) {
if (someParem == a) return new SubClassA();
if (someParem == b) return new SubClassB();
}
}
public class SubClassA extends SuperClass {
}
public class SubClassB extends SuperClass {
}
As you see you need some IF at some place ...

Related

Is there a way in Java to call different child method depending on which subclass is the object?

In my project I have a superclass and two subclasses extending from it. There is a method in the superclass that is overriden differently in each subclass.
I want to know if it's possible to introduce a method (in another class) that takes object of either subclass as a parameter and calls a method overriden in one of subclasses (depending on to which subclass does the object belong).
public class Superclass{
public int method(){return 0;}
}
public class Subclass1 extends Superclass{
public int method(){return 1;}
}
public class Subclass2 extends Superclass{
public int method(){return 2;}
}
public class CallingClass{
public static int dependantCall(Superclass parameter){return parameter.method}
I want to be able to do something like
Subclass1 subclassObject = new Subclass1;
System.out.println(CallingClass.dependantCall(subclassObject));
and get output
1
That is what Polymorphism is for! Defining the Superclass as a parameter type will allow you to pass either subclass in.
For example in your other class you can define it like this:
// classes Dog and Cat extend Animal and override makeNoise()
class Owner{
playWith(Animal a){
a.makeNoise();
}
}
Now the Owner can accept owner.makeNoise(cat) and owner.makeNoise(dog)
More reading: https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html
Yes, it is entirely possible. Here's how that method would look like:
public <T extends Superclass> void foo(T subclassObject) {
...
}
Or:
public void foo(Superclass obj) {
...
}
Note that in the above method, you can pass subclasses' objects as well (they are covariant data types).
This is what Java does by default when you create subclases, so no need to do anything special. Each object carries it's type information at run time, and the method invoked would always be the most specific one for the object. Example:
public class Doer {
public void doSomething() {
// Body presence
};
}
public class Painter extends Doer {
#Override
public void doSomething() {
// Paint here
}
}
public class Manager extends Doer {
#Override
public void doSomething() {
// Micromanage here
}
}
// Elsewhere in your code:
public void busyness(Doer doer) {
doer.doSomething();
}
A style note: if it is possible, one should prefer using interfaces instead of base classes (base classes those should be used only if you want to share implementation between subclasses). Example with interfaces:
public interface Doer {
void doSomething();
}
public class JackOfAllTrades implements Does {
#Override
public void doSomething() {
// Do whatever necessary
}
}
// Client code stays exactly the same as above:
public void busyness(Doer doer) {
doer.doSomething();
}
Note that in Java a class can have only one base class but can implement multiple interfaces.
#Override annotations are not strictly required, but they help Java compiler to spot some errors for you (e.g. if you misprint method name).
In your example it would look like
public class CallingClass {
public static int dependantCall(Superclass parameter) {
return parameter.method();
}
}
Subclass1 subclassObject = new Subclass1();
System.out.println(CallingClass.dependantCall(subclassObject));

Dynamic return type of implementation declared in abstract method

I am looking for a way to have, in an abstract method, the return type to be the one of the implementation calling the method.
In other terms, I would like to write something like that:
public class GenericClass {
public <T extends GenericClass> T returnMyself() {
return (T)this; // Compiler warning, unsafe cast
}
}
public class Implem1 extends GenericClass {}
public class Implem2 extends GenericClass {}
public class Main {
public static void main(String[] args) {
Implem1 implem1 = new Implem1();
Implem1 again1 = implem1.returnMyself(); // Works fine, the type is inferred by the type of again1, I think
Implem1 again2 = implem1.<Implem1>returnMyself(); // Works fine, the type is explicitly asked by <Implem1>
Implem2 again3 = implem1.returnMyself(); // Works fine while it shouldn't.
}
}
What I am looking for is a way to declare the method so that at compilation time, returnMyself() can only return the type of the implementation invoking it (in my example, implem1 is of type Implem1), and ensure the code invoking cannot mistake/mix the types.
I searched quite a lot but couldn't find my answer anywhere (some topics seem similar but want a more general case, not explicitly the type of the implementaion invoking the method).
Some answers were correct, but always implied to override the method in each Implementation class, which may be cumbersome and bug-prone on my side. I'm ideally looking for a method that i would have to write only once in the Abstract class.
Any help/answer appreciated :D
You can do it like this:
public class Parent {
public Parent returnMyself() {
return this;
}
}
public class Child extends Parent {
public Child returnMyself() {
return this;
}
}
This is no problem because if you store a Child instance in a Parent variable then you expect a Parent return type of returnMyself(). Even if it is actually a Child object, the Child returned by returnMyself() extends Parent so there you go.
Since you mention abstract in your problem description, how about follow a model similar to Java's Enum class, where the generic type is in the class definition?
public abstract class GenericClass<T extends GenericClass> {
public abstract T returnMyself();
}
public class Implem1 extends GenericClass<Implem1> {
#Override
public Implem1 returnMyself() {
return this;
}
}
public class Implem2 extends GenericClass<Implem2> {
#Override
public Implem2 returnMyself() {
return this;
}
}
public class Main {
public static void main(String[] args) {
Implem1 implem1 = new Implem1();
Implem1 again1 = implem1.returnMyself(); // Works fine
Implem1 again2 = implem1.returnMyself(); // Works fine
Implem2 again3 = implem1.returnMyself(); // Does not compile
}
}
Since you want to write these methods inside of subclasses, this appears to be possible. You can override a method and have a different return type as long as the new return type is an extension of the old one:
Can overridden methods differ in return type?

Java: Return an object that extends an abstract class which takes arguments

I've got an interface
public interface I
{
public AnAbstractClass k(); //Abstract Class constructor takes two arguments
}
For an implementation of this interface's method I want to return a generic object which extends that AbstractClass and also give it its two argument constructor
To clarify what I want to achieve. In a class which implements I:
public AnAbstractClass k()
{
//return a new implementing AbstractClass object AbstractClassObject(arg1,arg2)
}
Constructors are not inherited, so subclasses of AnAbstractClass won't necessarily have a two-argument constructor. If a subclass does have a two-argument constructor, there is nothing stopping you from creating an instance of that subclass using the two-argument constructor and returning it:
public abstract class AnAbstractClass
{
public AnAbstractClass(String foo, String bar) {
System.out.format("created with (%s, %s)\n", foo, bar);
}
}
public class BaseClass extends AnAbstractClass
{
public BaseClass(String foo, String bar) {
super(foo, bar);
}
}
public interface I
{
public AnAbstractClass k();
}
public class Implementation implements I
{
#Override public AnAbstractClass k() {
return new BaseClass("hello", "world");
}
}
public class Demo
{
public static void main(String[] args) {
I i = new Implementation();
AnAbstractClass a = i.k();
}
}
There are sophisticated solutions for this problem (roughly: Everything that is related to dependency injection). However, in this case, there are not so many options: Someone HAS to provide these arguments, and they obviously can not be passed to the interface method. So you'll probably need something like
class Creator implements I
{
private Object arg0;
private Object arg1;
void setArgs(Object arg0, Object arg1)
{
this.arg0 = arg0;
this.arg1 = arg1;
}
#Override
public AnAbstractClass k()
{
return new ConcreteClassExtendingAnAbstractClass(arg0, arg1);
}
}
The drawback is that this interface might become more or less useless: If it was designed to be a factory, you can no longer use it in its abstract form...
I i = obtainFromSomewhere();
AnAbstractClass a = i.k();
but you always have to know the particular type
Creator i = obtainFromSomewhere();
i.setArgs(..., ...);
AnAbstractClass a = i.k();

passing concrete factory into abstract factory class - java

I'm creating a abstractFactory class and I want to be able to send the concrete factory as a parameter. This way I can remove the if/else chain inside my abstract class.
My problem is I'm not sure how to typecast it back to the concrete class within my abstract class in order to call the createVehicle() method.
car = UniversalVehicleFactory.getFactory().createVehicle(CarFactory);
plane = UniversalVehicleFactory.getFactory().createVehicle(PlaneFactory);
Inside UniversalVehicleFactory I have the method createVehicle which is the method I'm having a problem with. What I'm trying to achieve is: take the parameter, determine its class and cast it to that, then call its internal createVehicle class.
public Vehicle createVehicle(AbstractFactory factory) {
// I want to take factory,
// cast it to the concrete factory, and
// call createMethod() on the factory
return factory.getInstance().createVehicle();
}
Help with this problem much appreciated!
I'll answer your question, but I'm curious why you want a universal factory to call a method of an abstract factory, if indeed you have to supply an instance of that factory as a parameter; you would be better off just invoking the creation method of the abstract factory directly.
Generics were invented for this purpose.
interface Factory< T > {
T make();
}
public class CarFactory implements Factory< Car > {
Car make() { ... }
}
public class PlaneFactory implements Factory< Plane > {
Plane make() { ... }
}
public class UniversalVehicleFactory {
public < T extends Vehicle > T make( Factory< T > factory ) {
return factory.make();
}
}
You'll notice that UniversalVehicleFactory doesn't implement Factory< T >.
I think you are trying to apply Abstract Factory pattern here. Here are my solution:
You can have interface VehicleFactory and factory classes:
interface VehicleFactory {
Vehicle createVehicle();
}
class CarFactory implements VehicleFactory {
public Vehicle createVehicle() {
return new Car();
}
}
class PlaneFactory implements VehicleFactory {
public Vehicle createVehicle() {
return new Plane();
}
}
Then if you want to centralize all the factory, you can have a UniversalVehicleFactory:
class UniversalVehicleFactory {
private Map<Class<T extends VehicleFactory>, VehicleFactory> factories;
static {
factories = new HashMap<Class<T extends VehicleFactory>, VehicleFactory>();
factories.put(CarFactory.class, new CarFactory());
factories.put(PlaneFactory.class, new PlaneFactory());
}
public static VehicleFactory getFactory(Class<T extends VehicleFactory> factoryClass) {
return factories.get(factoryClass);
}
}
Then in your code, use can use it like this:
Vehicle car = UniversalVehicleFactory.getFactory(CarFactory.class).createVehicle();
Vehicle plane = UniversalVehicleFactory.getFactory(PlaneFactory.class).createVehicle();
Here is some generalized code that might help you out:
public class A
{
public void paint(Graphics g)
{
}
}
public class B extends A
{
public static void main(String args[])
{
A a = new A();
B b = new B();
// This is the only one that won't work, because a is not an instance of b.
if(a instanceof B)
((B)a).draw(new Graphics());
if(b instanceof B)
((B)b).draw(new Graphcis());
if(a instanceof A)
((A)a).paint(new Graphics());
if(b instanceof A)
((A)b).paint(new Graphics());
}
public void draw(Graphics g)
{
}
}
instanceof is a great tool to use before typecasting to avoid errors. I hope this helped, if it was too general and you want me to apply it more to your situation let me know.

java subclass have method to return its class

Ok, maybe this is a stupid question. But i'm just wondering if this can be done in java.
abstract public class ParentClass<T> {
abstract public T getTest();
}
in the subclass
public class SubClass extends ParentClass<MyObject> {
public MyObject getTest() {
// I can return the object with class MyObject
return null;
}
}
My question is can I return the class type in the child method? I mean, is it can be done by adding some code in the ParentClass, so I can do this below?
For example
public class Sub1Class extends parentClass<Object1> {
public Object1 getTest() { }
// I want to have a method that return it's class in the superclass
public Sub1Class getItClassObject() { }
}
other example
public class Sub2Class extends parentClass<Object2> {
public Object2 getTest() { }
// I want to have a method that return it's class in the superclass
public Sub2Class getItClassObject() { }
}
one example again
public class Sub3Class extends parentClass<Object3> {
public Object3 getTest() { }
// I want to have a method that return it's class in the superclass
public Sub3Class getItClassObject() { }
}
if you see, method getItClassObject in Sub1Class, Sub2Class and Sub3Class will follow it's class. But I don't want to add same method for every subclass, just want to add some code (if feasible) in the ParentClasss, so in the subclass, I just can call getItClassObject directly without write all the code in every subclass.
Usually I add method in ParentClass like this.
abstract public class ParentClass<T> {
abstract public T getTest();
public Object getItClassObject() { }
}
so in the subclass I just instance the class, but I have to cast again :(
Sub1Class sub1Class = new Sub1Class();
Sub1Class after1Cast = (Sub1Class) sub1Class.getItClassObject();
Sub2Class sub2Class = new Sub2Class();
Sub2Class after2Cast = (Sub2Class) sub2Class.getItClassObject();
I think it cannot be done in java. But I don't know if there is a clue to solve this. Thanks
This is what you want I think. The following compiles:
abstract class A {
public abstract A getA();
}
class B extends A {
// Declared to return a B, but it still properly overrides A's method
#Override
public B getA() {
return new B();
}
}
class C extends A {
// Declared to return a B, but it still properly overrides A's method
#Override
public C getA() {
return new C();
}
}
As you can see, A declares that the getA() method returns an A. But, you can restrict the return type in subclasses as shown.
I'm not sure if I understand your intent correctly, but I think the built-in Object.getClass() method will do what you want. Given classes defined as:
public abstract class ParentClass<T> {
public abstract T getTest();
}
class SubClassString extends ParentClass<String> {
public String getTest() {
return "";
}
}
class SubClassInteger extends ParentClass<Integer> {
public Integer getTest() {
return Integer.valueOf(0);
}
}
getClass() will return the correct run-time class
public static void main(String[] args) {
SubClassString subString = new SubClassString();
// displays "class SubClassString"
System.out.println(subString.getClass());
SubClassInteger subInteger = new SubClassInteger();
// displays "class SubClassInteger"
System.out.println(subInteger.getClass());
ParentClass<?> parentInstance = new SubClassInteger();
// displays "class SubClassInteger"
System.out.println(parentInstance.getClass());
}
The only way I can think of is by telling the parent class what the subclass is when you extend it (just like you did with 'T'). Eg:
public abstract class ParentClass<T,U> {
abstract public T getTest();
abstract public U getItClassObject();
}
They you define your subclass like so:
public class Sub1Class extends ParentClass<Object1,Sub1Class> {
public Object1 getTest() { }
public Sub1Class getItClassObject() { }
}
Then you can do what you want without the typecast:
Sub1Class sub1Class = new Sub1Class();
Sub1Class after1Cast = sub1Class.getItClassObject();
If your objects have no-arg constructors (or some consistent form of constructor across all of them), you can use reflection to do it. Some pseudocode would be
public class MyClass {
public MyClass instantiateType() {
Class<?> actualClass = getClass();
return actualClass.newInstance();
}
}
This is using the runtime type of the class, so subclasses will return their type. This works only for a no-arg constructor though.

Categories

Resources