Home > Mobile >  Creating an intance of a Class via method of an Interface implemented by that class
Creating an intance of a Class via method of an Interface implemented by that class

Time:04-15

I want to call the constructor of a class inside the method of an interface.

For example, if I have two classes B and C and they both implement SomeInterface, so that each of them has method foo().

interface SomeInterface {
    public SomeInterface foo();
}

class B implements SomeInterface {
    public B(int fst, int snd) {}
    
    @Override
    public SomeInterface foo() {
        return new B(1, 1);
    }
}

class C implements SomeInterface {
    public C(int fst, int snd) {}
    
    @Override
    public SomeInterface foo() {
        return new C(1, 1);
    }
}

And let's say, for the sake of this question, that I have a lot more classes that implement SomeInterface and they all do the same thing, that is return new <nameoftheclass>(1,1) and all these classes extend the parent class A.

Is there a way for me to create only one method in A such that if any of these classes use the foo method that is found in A it will call their constructor and just like that save me lines of code?

CodePudding user response:

You can do something like this with reflection, although it will be prone to failure.

    public SomeInterface foo() {
        Constructor<? extends SomeInterface> c = getClass().getConstructor(int.class, int.class);
        return c.newInstance( 1, 1);
    }

You'll have to manage some exceptions, but is this what you're after?

The question would then be, where can this be used? Interfaces don't have a common constructor.

public interface SomeInterface{
    default SomeInterface another(){
        Constructor<? extends SomeInterface> c = getClass().getConstructor(int.class, int.class);
        return c.newInstance( 1, 1);
    }
}

That would work provided whatever the implementations try to use it have that constructor. There is no guarantee that constructor exists though. Maybe you would want it on an abstract class?

CodePudding user response:

use the foo method that is found in A it will call their constructor and just like that save me lines of code?

You are getting it wrong. Class design decisions must be based on use cases and relationships of the classes in your domain. If your main criteria will be to spare some lines of code, you can end up with a coffee machine extending combine harvester because both of them have tree dimensions. Don't take a pill if you have no headache.

Parent class A that you've mentioned doesn't make any sense because method foo() returns an instance of SomeInterface interface which A doesn't implement (because if it does, its subclasses don't need to declare to implement it). I.e. A and SomeInterface are not compatible and compiler will not allow to type cast between them. Therefore, I'll omit the parent class.

As an example, the "template" you've provided might be useful, will be a situation when classes with similar functionality need to grouped together.

The interface can serve as a single entry point for the user of the code. Every class will implement the behavior defined by the interface, and only through the interface it'll be possible to get an instance of the class with a particular flavor of functionality. The actual classes will be hidden from the user.

Similarly, abstract class NumberFormat from the JDK provides a way to obtain different kinds of formatters, but actual implementations are hidden are not exposed (the approach shown below is far more simple than the actual way of how factory methods of the NumberFormat are implemented).

Note, interface and its implementations must reside in the same package.

public interface BaseInterface {
    public static BaseInterface getInstance(Classifier classifier) { // factory
        return switch(classifier) {
            case A -> new A();
            case B -> new B();
        };
    }
    
    void doSomeThingUseful(); // behaviour that every class should implement
}

enum Classifier { A, B }

class A implements BaseInterface {
    A() {}
    
    @Override
    public void doSomeThingUseful() {
        System.out.println("Class A");
    }
}

class B implements BaseInterface {
    B() {}
    
    @Override
    public void doSomeThingUseful() {
        System.out.println("Class B");
    }
}

main() - demo

public static void main(String[] args) {
    List<BaseInterface> items = List.of(BaseInterface.getInstance(Classifier.A),
                                        BaseInterface.getInstance(Classifier.B));
    for (BaseInterface item: items) {
        item.doSomeThingUseful();
    }
}

Output

Class A
Class B
  • Related