1

Let's say that I have 2 classes: Foo and Bar.

`Foo` {
  List<Bar> bars
  String bippy()
  int boop()
}

`Bar` {
 int biz()
 String baz()
}

Observe that Foo's fields include a List<Bar>. Note that Foo has separate fields from Bar, but they share some fields.

Let's say that I have a method, f.

def f(Foo foo) {
 ...
}

This method, f, currently accepts only a Foo type. However, this method also needs access to a Bar.

When I need to pass in a Bar, I could simply create a new Foo with a single Bar in List<Bar> - but I don't like this assumption. Placing this assumption in the code won't (and should not be) easily understood by the user of it.

So, I decided to create an interface, Something, that both classes implement:

interface Something {
 Optional<String> getBippy()
 Optional<int> getBoop()
 Optional<int> getBiz()
 Optional<String> getBaz()
}

With this interface, I can now update f's argument to be of type Something.

As a result of this new interface, Foo's and Bar's implementations will return "missing" values if the implementing class fails to have the field expected in the interface.

Example:

Foo implements Something {
 List<Bar> bars
 getBippy() { return bippy }
 getBaz()   { return None }
 ... // remaining implementations
}

This approach will work, I believe, provided that the developer who consumes the f method passes in the right type.

How's my approach? In particular, I'm curious if there's a more type/statically safe approach.

  • 4
    It looks fishy that one method should be able to work with two such completely different classes. Are you sure that it isn't better to split f in two functions (one that works on a Foo and one that works on a Bar)? – Bart van Ingen Schenau Dec 13 '14 at 16:49
  • That's a very good point. I was leaning towards code re-use (so that I wouldn't need to write two f methods: fFoo and fBar. In addition, I would need to write more helper functions if I'm going to support these two functions. But, no doubt, it would be type-safe. – Kevin Meredith Dec 13 '14 at 16:50
  • That interface doesn't guarantee the argument has a Baz (or any other field), and having to modify existing types isn't exactly good code reuse. (Ideally, if I give you some type, you shouldn't have to modify it at all regardless of the context you want to use it in.) I would just write a second function that has a Foo and Bar argument and make it the caller's problem to figure out where to get the Bar. – Doval Dec 13 '14 at 19:04

Your Answer

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

Browse other questions tagged or ask your own question.