3

It's preferable to write programs that depend on interfaces rather than on superclasses, but what if you want a class to have certain variables? Sometimes you want a class to implement a certain variable. (For example, imagine you have a datasource interface, and want all classes to implement a "String user").

In this case, I can see making an abstract class "datasource", which other classes could then extend. But this means they can't extend another class anymore, due to no multiple inheritance in Java.

So, to conclude, if I would have the above scenario, should I rethink my design, or is there a pattern I don't know about that I could follow to achieve the interface-with-variable design?

7
  • 4
    Why do you need a field (which other best practices dictate shouldn't be public to begin with) rather than a getter/setter?
    – user7043
    Oct 22, 2014 at 19:56
  • 1
    I could put in the interface 'public void setUser()', but than the actual implementation can still do pretty much whatever it wants. The classes that implement the interface NEED the String. I'm not sure where I said the field should be public? It can be private to each class still, I just need to know the classes that implement a certain interface also have a certain variable. (what they do with it can be different) Oct 22, 2014 at 20:04
  • replace inheritance by delegation? "...This approach is so common, there is even an Eclipse refactoring exactly for this purpose"
    – gnat
    Oct 22, 2014 at 20:13
  • If you inherit state from interfaces, it sounds like you could easily run into a shared inherited state problem
    – Jack
    Oct 22, 2014 at 21:05
  • 3
    Don't rethink your design, rethink your programming language. Depending on your situation, traits/mixins for example could be a good solution. Also, implements is not per se better than extends! It's two different tools for two different problems.
    – valenterry
    Oct 23, 2014 at 7:10

4 Answers 4

9

If you need to share implementation, then use inheritance. That's what it's for. But use an interface as well, and treat the fact that inheritance is being used by the implementations as an implementation detail: client code shouldn't need to know.

For instance, see the library classes List, AbstractList, ArrayList and LinkedList. There are common implementation details of the two concrete classes which are shared by them both inheriting from AbstractList. But as a client of them, this is an unnecessary detail which we don't ever use... we only care that they both implement the interface, List.

7

The premise of this question is a bit confusing. You cannot "implement a variable". It either exists or it doesn't. Further, "wanting" a class to contain a variable either means:

  • You own the code, so just put the variable in each of the implementing classes (via base class if so desired).
  • You don't own the code (future implementations of this interface). You can't dictate their implementation, only the specification, so don't worry about what they might name their user variable.

Beyond that, your options are limited by language. In C#, your interface could contain a property public String User { get; set; }. In Java, you are limited to using a base class, or possibly considering Java 8's default methods in interfaces.

3

You can add the following to the interface:

public void setUser(String s);
public String getUser();

That way implementors are kind of forced to have a username variable in their state. Although implementors may name it whatever they like.

That way you continue simulating multiple-inheritance through interfaces.

Any class extending another one that implements the interface can access the variable with super.getUser(); or you can even make the state variable protected, but that's an implementation detail.

0

The very fact of asking whether you need to rethink your design indicates that you need to rethink it.

Result of your rethinking should be that you either (1) redesign the code so that it follows general practice for objects to expose behavior, not data, or (2) identify it as exceptional case where deviation of general norm is clearly justified (eg Data Transfer Object).


Technical way to make field usage enforced by interface is explained in this answer to prior question:

...Here you find a detailed example how to replace inheritance by delegation. This approach is so common, there is even an Eclipse refactoring exactly for this purpose

Applied to your case, above approach could look as follows.

First, you create a class (plain class, nothing special) with desired field(s):

public class Data {
    private String user;
    public void setUser(String user) { this.user = user; }
    public String getUser() { return user; }
}

Next, you define the interface that allows to delegate to above class:

public interface DataSource {
    public Data delegate();
    //... other methods here
}

As a result, any object implementing DataSource interface will be also forced to provide Data functionality to work with user String.

Worth reminding once again that you better do so only if this is clearly justified - besides already mentioned issue of exposing data instead of behavior, this also goes against the Law Of Demeter.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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