20

Suppose I have following class structure:

class Base {}
class A extends Base {}
class B extends Base {}
class C extends Base {}

I want to write method, that accepts instances of A and B but not instances of C.
Can I achieve it in Java?

I know this is not good inheritance situation (A and B should have common parent different from C), but I am only curious is in Java way to handle situation like this.

EDIT:
!!!
I know that better inheritance will resolve problem. I am only curious, if Java have some standard mechanism to solve problem like that.
!!!

Bhavik Ambani
  • 6,557
  • 14
  • 55
  • 86
Michał Herman
  • 3,437
  • 6
  • 29
  • 43

9 Answers9

43

Use an interface and have only A and B implement it.

Paul Bellora
  • 54,340
  • 18
  • 130
  • 181
NimChimpsky
  • 46,453
  • 60
  • 198
  • 311
13

Can you use an interface? e.g.

class Base {}
interface MyGenericInterface {}
class A extends Base implements MyGenericInterface {}
class B extends Base implements MyGenericInterface {}
class C extends Base {}

That way, the method can accept implementations of MyGenericInterface, and since A and B implement the interface but C does not, it will accept instances of A and B but not C, as required.

NickJ
  • 9,380
  • 9
  • 51
  • 74
8

If something should accept A, B but not C then you should reconsider why C is inheriting from Base in the first place. You could add an extra layer of inheritance:

   ---Base---
   |        |
--Sub--     C
|     |
A     B

Then you could allow your method to only accept objects of type Sub. Sub doesn't even have to do anything, and they're all, technically, also Base.

A quicker solution would be a dirty if( arg.instanceof(C) ) though...

Jimmy Thompson
  • 1,004
  • 7
  • 17
8

You can handle it at runtime using exception:

void genericMethod(Base arg_in)
{
    if(arg_in instanceof C)
    {
        throw IllegalArgumentException("C class not accepted."); 
    }

    ...
    ...
}
Azodious
  • 13,752
  • 1
  • 36
  • 71
8

A type-hierarchy should not be changed only because you want to have such a method. But the case that you want to have such a method may indicate you should think over your type-hierarchy.

But if you are sure your types are well designed, what about this approach:

    public class T {

        public void doSomething(final A a) {
            doSomthing(a);
        }

        public void doSomething(final B b) {
            doSomthing(b);
        }

        private void doSomthing(final Base b) {

            // Here is the implementation

        }

    }
Daniel Pryden
  • 59,486
  • 16
  • 97
  • 135
MrSmith42
  • 9,961
  • 6
  • 38
  • 49
  • I don't know what you were intending with the `final` keyword there, but it won't prevent a widening conversion from occurring at the call site. Since every instance of `C` is an instance of `B`, it will always be possible to pass instances of `C` into your `doSomething()` method. – Daniel Pryden Dec 22 '12 at 01:32
  • Why do you think "C is an instance of B" ? A,B,C all only extend Base – MrSmith42 Dec 22 '12 at 14:01
  • 'final' has nothing to do wthe the functionality. Just a codeing convention I am used to. – MrSmith42 Dec 22 '12 at 14:03
  • Hmmm... on revisiting this, it appears I misread the question. My apologies. – Daniel Pryden Dec 23 '12 at 03:06
3

I guess the answer to your questions is "No, java does not have a standard way of dealing with such a problem". And if you have this problem then you can look at other answers here, like fixing the inheritance or using the clever technique given by MrSmith42.

Community
  • 1
  • 1
Waqas Ilyas
  • 3,116
  • 1
  • 17
  • 27
  • 4
    @MichałHerman correct ? 17 - 1 ... blimey, this is like being at work. – NimChimpsky Dec 21 '12 at 15:17
  • @NimChimpsky don't worry, there's badges for this sort of thing. :) – Mike G Dec 21 '12 at 16:15
  • 3
    Yes, I for me this answer is correct, because I asked IF Java have some build mechanism to deal this kind of problems. Not HOW to deal with this type of problems by myself, because this I already know. – Michał Herman Dec 21 '12 at 19:43
2

You can use instanceof to check if an object is of a certain type.

Better idea would be better inheritance structure, of course.

gefei
  • 18,922
  • 9
  • 50
  • 67
  • To be clear: In Java, `instanceof` works for subclasses. That is, `C c = new C(); c instanceof B` will return true. If you want to exclude `C`, you need to check for it explicitly. (Adding a comment because at first glance this answer wasn't clear to me.) – Daniel Pryden Dec 22 '12 at 01:34
2

Generics is for type safety. Period. Not to "allow" or "disallow" arbitrary things. There is no type-safety reason to allow A and B and not C.

newacct
  • 119,665
  • 29
  • 163
  • 224
0

Try below snippet

public <T extends Base> void setAuditorDetails(T model) 
{
         if(!(T instanceof C)){

              // Your Business logic

         }
}
Vikram
  • 179
  • 1
  • 7