They need to be of the same type to be used like that. Luckily, we can fix this by implementing a fitting functional interface.
public class Something implements Runnable {
public String name;
public String description;
@Override
public void run() {
System.out.println("something");
}
}
Runnable has the method run() that takes no arguments and returns nothing (aka it has to do something).
So this works only if you're not actually going to be using the String array as an argument, as you don't include it in your calling of run(). However, if you do need it, you must change the implemented interface to Consumer instead of Runnable, with accept() instead, as this method actually takes an argument as opposed to run().
public class Main {
public static void main(String[] args) {
HashSet<Runnable> things = new HashSet<>();
things.add(new Something());
things.add(new Something2());
things.forEach(thing -> {
thing.run();
});
}
}
Now, we set the HashSet to the type of the implemented interface, and it works!
Here's the other class:
public class Something2 implements Runnable {
public String name;
public String description;
@Override
public void run() {
System.out.println("something2");
}
}
Now you can create as many classes as you want and have their methods do different things, while still being able to gather them in the same set(as long as they implement the same type)!
Side note: if you didn't need the attributes, you could've used lambda expressions to implement different versions of run() (or accept(), or any other functional interface-method).
public void run(String[] args)?interface MyRunnable { void run(String[] args); }and have each of your classes implement it. Then useHashSet<MyRunnable>.