0

I created the following class:

public class Abuser {
    <T extends Spam> List<T> createSpam() {
        List<T> lst =  new ArrayList<>();
        T s = new T();
        s.prepareAd();
        lst.add(s); 
        // the above is done unknown number of times
        return lst;
    }
}

to use with classes like this:

public class Spam {
    void prepareAd() {}
}
public class WildSpam extends Spam {}
public class MildSpam extends Spam {}

in the following way:

Abuser a = new Abuser();
Lost<WildSpam> wSpam = a.createSpam();
List<MildSpam> mSpam = a.createSpam();

How to make that work with a minimum fuss?

vkamenen
  • 41
  • 4
  • 1
    Well, you do know it in advance. So create two methods instead of just one: createWildSpam() and createMildSpam(). – JB Nizet Oct 02 '16 at 07:12
  • 1
    The utility of polymorphism in Java (or any OOP language) is precisely that you _want_ to use a `Spam` object without knowing what its particular implementation is. Can you clarify what you are trying to do here? – Tim Biegeleisen Oct 02 '16 at 07:12
  • Possible duplicate of [*Create instance of generic type in Java?*](http://stackoverflow.com/questions/75175/create-instance-of-generic-type-in-java) – T.J. Crowder Oct 02 '16 at 07:15
  • @JB Nizet, class Abuser does not want to know about specific types of Spam – vkamenen Oct 02 '16 at 07:22
  • @Tim, consider Abuser a general purpose lib. The utility is to use WildSpam/MildSpam methods implicitly from within the lib without the lib even knowing about various types of Spam, but only about their parent class – vkamenen Oct 02 '16 at 07:26
  • @T.J., thanks, it looks similar. – vkamenen Oct 02 '16 at 07:28
  • 2
    @vkamenen then it should probably not be the one instantiating Spam objects. You can use `createSpam(Supplier spamSupplier)` as method signature, and call it as `createSpam(WildSpam::new)`. – JB Nizet Oct 02 '16 at 07:32
  • @JB, and what if createSpam have to create a lot of objects (as is in my case, although I simplified It)? – vkamenen Oct 02 '16 at 07:37
  • You'll then call it with `createSpam(SomeOtherSpam::new)`, or `createSpam(YetAnotherSpam::new)`, or whatever. What's the problem? – JB Nizet Oct 02 '16 at 07:39
  • shouldn't it be Supplier? – Turo Oct 02 '16 at 07:44
  • @JB, only createSpam knows how many objects has to be created – vkamenen Oct 02 '16 at 07:44
  • 1
    createSpam(), in your example, creates a single Spam object. So either your example is wrong, or your comment is wrong. You need to ask us the real question you would like us to answer. – JB Nizet Oct 02 '16 at 07:46
  • @Turo yes, if the caller needs to know the type of the Spam being returned. If it just needs to know it's a Spam, then it can be Supplier. – JB Nizet Oct 02 '16 at 07:47
  • @Turo, I dont know what you mean – vkamenen Oct 02 '16 at 07:54
  • @JB, OK I editted it – vkamenen Oct 02 '16 at 07:56
  • So it creates several instances of the same type? Then call the supplier in a loop: `for (int i = 0; i < 10; i++) { list.add(supplier.get()); }`. – JB Nizet Oct 02 '16 at 08:00
  • @vkamenen it was a question to JBs suggestion, and he answered it. – Turo Oct 02 '16 at 08:01
  • @JB, your supplier needs to be told what objects to create. It is the same issue. Try to implement it. – vkamenen Oct 02 '16 at 08:10
  • Your code has `List mSpam = a.createSpam();`. So the caller **knows** what type of Spam to create: `MildSpam`. So it can pass a MildSpam::new. If neither the caller nor the callee know what to create, how could something be created? – JB Nizet Oct 02 '16 at 08:13
  • @JB, the issue is the lack of having types as first class objects in Java. In the concrette case the issue is how to tell a supplier that It shall be suppliying a certain kinds of objects – vkamenen Oct 02 '16 at 08:28
  • MildSpam::new creates instances of MildSpam. SomeOtherSpam::new creates instances of SomeOtherSpam. How does that not tell the supplier what kind of object to create? – JB Nizet Oct 02 '16 at 08:41
  • @JB, as I said - try to implement it and you will see where the problem is – vkamenen Oct 03 '16 at 07:49
  • @vkamenen: no problem at all. http://ideone.com/MyUixt – JB Nizet Oct 03 '16 at 15:34
  • @JB, You are right and I stay corrected. Thanks! I would have set this as an answer if I could – vkamenen Oct 04 '16 at 12:36
  • @JB, as far as I see this is a new feature introduced in Java 8. Unfortunatelly I have to use an older version – vkamenen Oct 04 '16 at 12:43

1 Answers1

-1

Java should know what objects have to be created. You must pass some parameter to your method to inform it.

Like this:

public class Abuser {
<T extends Spam> T createSpam(T a) {
    T s = null;
    try {
        Class cls = Class.forName(a.getClass().getName());
        s = (T) cls.newInstance();
        s.prepareAd();
        // the above is done unknown number of times
    } catch (Exception e) {
        e.printStackTrace();
    }
    return s;
}
}

Use it like this:

    Abuser a = new Abuser();
    WildSpam wSpam=new WildSpam();
    wSpam=a.createSpam(wSpam);
    MildSpam mSpam = new MildSpam();
    mSpam=a.createSpam(mSpam);

This code is for one object not a list of objects.