1

In a competition application I'm designing there are several types of prize draw, each of which needs to act upon an entry object in some way. So the first lines of code I wrote defined an interface.

interface PrizeDrawInterface
{
    public void enter(EntryInterface entry);
}

Here's the problem which I'm not sure how to solve. It turns out the implementations are going to require more specific objects than EntryInterface.

class RandomPrizeDraw implements PrizeDrawInterface
{
    public void enter(WinnableInterface entry)
    {
        if (someRandomCondition) {
            entry.setWinner(true);
        }
    }
}

class QuizPrizeDraw implements PrizeDrawInterface
{
    public void enter(QuizContestantInterface contestant)
    {
        if (contestant.getAnswer().isCorrect()) {
            contestant.givePrize();
        }
    }
}

Obviously the above code isn't going to work, as the enter() method signatures are not compatible.

My current best solution is to add an extra method to the prize draws and delegate type enforcement there, so they might look like this:

class RandomPrizeDraw implements PrizeDrawInterface
{
    public void enter(EntryInterface entry)
    {
        this.doEnter(entry);
    }

    public void doEnter(WinnableInterface entry)
    {
        if (someRandomCondition) {
            entry.setWinner(true);
        }
    }
}

But to me this looks more like a quick fix than a clean solution.

Does this problem have a name? Is my interface not fit for purpose? Is there a cleaner solution than the one I have proposed?

6
  • 1
    How do you intend to use this interface and the implementations? Do you really need a single interface? You'll have to match the right implementation with each type of parameter. How do you plan to do that? Wouldn't a generic interface solve your problem? – Francesc Castells Feb 27 '18 at 22:32
  • The implementation will be composed by a Competition class which will need to invoke the enter logic as soon as an entry is created, eg this.prizeDraw.enter(entry). There's a good chance the language I'll end up using to implement this doesn't support generics :( – Sam Hastings Feb 27 '18 at 22:39
  • Expanding on my previous answer, I ideally need to be able to decorate the implementations as well. – Sam Hastings Feb 27 '18 at 22:46
  • 1
    OK. Generics would solve your question as it is, but the most important of my questions was "How do you match the implementation of your interface with the enter parameter type?". Will you match them at development time or execution time? If how to do this matching is your fundamental problem, then do something like what David Arno suggests. – Francesc Castells Feb 27 '18 at 23:09
  • The pragmatic solution is of course if(!(entry is QuizContestantInterface)) throw new Exception("Error - not a valid quiz contestant!"); – user253751 Feb 28 '18 at 5:15
3

Based on the code you have shown, my gut feeling is that enter is a constructor masqerading as a method.

For example, at the point where you want to invoke RandomPrizeDraw.enter(WinnableInterface entry), you have already established that RandomPrizeDraw and WinnableInterface are coupled. So trying to express that, and other (different) couplings via an interface really doesn't make sense.

So I think you'd be better off using some sort of factory that returns an implementation of PrizeDrawInterface based on the implementation type of EntryInterface and do away with enter completely.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.