2

as a follow up on my previous question Having a function with combined generic bounds such as:

<T extends Foo & Bar> void doStuff(T argument) {
  //do stuff wich should only be done if arguments is both foo and bar
}

Because this is not castable from a unspecified object, you need to have knowledge of some object which actually implements these interfaces. it seems to me that needing to know the specific type of the object argument to pass to doStuff(T a) is a violation of Demeter's law.

The function doesn't specify the need to know the actual class (there could be many different ones), and i really don't want to know it as knowing this class increases the dependency in my code base.

is using these bounds an anti pattern? and if so how should one best avoid it?

the case scenario involved one interface specifying the object is persistent and the other specified object having a related entity. the doStuff(T a) function in this case persisted the related entity when it was persisted. however nonpersistent entities can also have a related entity, but should not be processed by the doStuff(T a) function

Community
  • 1
  • 1
pvgoddijn
  • 12,638
  • 15
  • 47
  • 56

3 Answers3

4

I wouldn't consider combined generic bounds an anti-pattern. At least I've got some uses for them in my code. For instance, the following sample code finds the biggest Number instance in a collection using compareTo from the Comparable interface:

<T extends Number & Comparable<T>> T max(Collection<T> numbers)
Frank Grimm
  • 1,151
  • 7
  • 11
  • Why does T need to extend Number? Does it not work work on any type that is completely ordered? – Miserable Variable Nov 26 '08 at 11:02
  • Number actually makes a difference to the erased signature of the method (it will return Number instead of Comparable). In the more generic Collections.max it returns T extends Object & Comparable super T>, this is because the pre-1.5 method returned Object instead of Comparable. – Tom Hawtin - tackline Nov 26 '08 at 11:23
2

it seems to me that needing to know the specific type of the object argument to pass to doStuff(T a) is a violation of Demeter's law

I disagree. I don't see how

T<? extends Foo & Bar> void doStuff(T argument) 

requires any more knowledge of argument to pass then

T<? extends Foo> void doStuff(T argument) 

Or even more then just

void doStuff(T argument) 

In all cases you need to know something about argument and I don't think the first cases is demanding any more knowledge then others because it has two identifiers.

Miserable Variable
  • 28,432
  • 15
  • 72
  • 133
  • because in the first example we need to explicitly pass some class A implements Foo, bar, which means we need to know class A, while in the second example we only need to know the INTERFACE Foo (not the class B implements Foo) – pvgoddijn Nov 26 '08 at 11:12
0

The anti-pattern is casting.

However, fancy generics footwork may be confusing to non-advanced programmers. Usage of such types and method should be much easier than their implementation.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305