0

I am wondering if it is possible to make any implementation of a specific Interface take a specific action automatically at the time when the Interface itself is initialized. Something like below:

public interface MyInterface {

    public static final ArrayList<MyInterface> IMPLEMENTATIONS = new ArrayList<>();

    public static void init(){
        // Somecode...
    }

    void method1();

    void method2();

}

I would like that when the interface is initialized, like if the init method is called, then a new instance of each class that implements the interface is to be created and added to the ArrayList.

The purpose of having something like this is to essentially have a single program that can start any other program I write and want available. Essentially, it is started when the computer starts and then can be used to start any other program I have written, instead of my having to add each new program to the system auto-start folder.

Is something like that possible?

Anju Maaka
  • 263
  • 1
  • 10
  • 1
    I don't understand what you want. You cannot initialize an interface, you can only initialize classes. – Dorian Gray Jun 05 '19 at 12:09
  • Well that is not 100% true, the interface is somewhat "initialized", any static variables within it are assigned for example. See https://stackoverflow.com/questions/23096084/when-is-an-interface-with-a-default-method-initialized – Anju Maaka Jun 05 '19 at 12:34
  • What I want is to somehow, from within an unrelated class, know each and every class that implements a specific interface I have. – Anju Maaka Jun 05 '19 at 12:35
  • You have to call init specifically. Interfaces cannot have static {} block. For your other requirement, if you want to use spring library (not necessarily the container), you may want to look at this: https://mcoj.wordpress.com/2009/03/13/classpath-scanning or implement something similar your own ;-) – Jayr Jun 05 '19 at 13:11
  • @Anju You mean you want to have all instances of classes that implement a specific interface at runtime? – Dorian Gray Jun 05 '19 at 13:20

3 Answers3

1

Instead of using Interface, use abstract class. Further, inside that class, create a single argument constructor which accepts your abstract class as a parameter. And then in constructor, you can add that parameter in your ArrayList.

Then, inside main class, you can use org.reflections to create the instances of all the classes which extends your abstract class. And then call the init method where you can do operations on the list.

public class MyClass{
  private static final List<MyClass> IMPLEMENTATIONS = new ArrayList<>();
  public MyClass(MyClass myClass){
    IMPLEMENTATIONS.add(myClass);
  }
  public static void init(){
    // Do something with IMPLEMENTATIONS
  }
  abstract void method1();

  abstract void method2();

}

package com.mypackage; 
public class Child extends MyClass{
  public Child(){
    super(this);
  }
  // Implement other abstract methods
}

public class MyMainClass{
  public static void main(String[] args) throws IllegalAccessException, InstantiationException { 
    Reflections reflections = new Reflections("com.mypackage"); 
    Set<Class<? extends MyClass>> classes = reflections.getSubTypesOf(MyClass.class); 
    for (Class<? extends MyClass> aClass : classes){ 
      aClass.newInstance(); 
      }
    MyClass.init();
    }
}
Manish Bansal
  • 2,400
  • 2
  • 21
  • 37
  • That works mostly. It still needs each of the implementing classes to be created manually. I want to not have to do specifically that. – Anju Maaka Jun 05 '19 at 13:42
  • @AnjuMaaka Do you mean creating an implementing class? I think you can create an implementing instance on the fly, without a class in itself; I'm unsure about this, though. If yes, you could create a factory class/method to furnish you the instances without having to create classes. – Prometheos II Jun 05 '19 at 13:53
0

In addition to Manish's answer, in case in which you already inherit from a class; you could use an outside method, which would initialize the instances inheriting from your interface, through polymorphism.

It would give something around those lines:

public class MyInterfaceFactory {
    public static void initializeElements( MyInterface _element ) {
        MyInterface.IMPLEMENTATIONS.add( _element );
    }
}

Or you could do the addition to the Array in the constructor of every implementing class.

Prometheos II
  • 334
  • 3
  • 14
0

Your Question is too general to give a specific answer. However, (If I understood you correctly) I wrote an Open Source library MgntUtils that contains a small framework with feature called Self-populating factory. In the nutshell here it how it works: you can extend a framework provided Factory and write your own interface that will extend framework provided interface. Then you write several classes implementing your interface and once constructors for your classes are called each class inserts itself into a factory so, once your program starts (if something a Spring Boot or Spring framework for example) initiates your classes, your factory then is fully initialized and ready for use. Anyway here the relevant links to library and articles that explain the idea and use:

Article that explains the idea in more detail
article about MgntUtils library
Package description in javadoc that explains in detail how to use the feature
Full Javadoc
Github with library including sources and javadoc
Maven Central with all versions of the library

Michael Gantman
  • 7,315
  • 2
  • 19
  • 36