Ways to achieve effective Java traits?

安稳与你 提交于 2019-12-06 21:14:44

问题


Please let me know if this is inappropriate as formulated (in particular whether Programmers.SE or something would be better for the question.)

Alright. So I've got a number of 'traits' that I'm currently expressing as interfaces. Let's call them "updatable" and "destructible". Expressing them as interfaces has the downside that I can't share behavior between all "destructible" components; on the other hand, expressing these as abstract classes mean I can't mix and match without explicitly defining the mixed trait as another abstract class ("UpdateableAndDestructible") and furthermore this feels like an abuse of the abstract class functionality at that point. It's probably what I'll end up doing if there aren't cleaner ways of handling this, however.

What are my options as far as pure Java solutions to this conundrum? Is it possible for me to describe shared behavior and then mix and match as I see fit without having to explicitly describe every permutation I'll be using?


回答1:


Maybe you could achieve the goal by using a mix of interfaces and default implementations.

Like:

public interface Updatable {
  void updated();
}

public interface Loadable {
  void load();
}

public class DefaultUpdatable implements Updatable {
 ...
}

public class DefaultLoadable implements Loadable {
 ...
}

public class SomeObject implements Updatable, Loadable {
  private final Updatable updatable = new DefaultUpdatable();
  private final Loadable loadable = new DefaultLoadable();

  public void load() {
    this.loadable.load();
  }

  public void updated() {
    this.updatable.updated();
  }
}

Still noisy and maybe not as flexible as you would like but maybe a bit cleaner than doing the UpdatableAndDestructable thing.




回答2:


I don't think there is a pretty solution to this problem, but maybe a few workable ones depending on how much you despise the boilerplate.

You could define a trait as another class + interface, that takes the instance object as the first parameter. And them implement the interface with the class you want to have the trait. Then create stub methods that call the methods on the trait impl.

public class MyClass implements MyTrait {
    @Override
    public void doSomething() {
        MyTraitImpl.doSomething(this);
    }
}

And then for the trait itself:

public interface MyTrait {
    public void doSomething();
}

public class MyTraitImpl {
    public static void doSomething(MyTrait obj) {
        // do something with obj
    }
}

As Ernest Friedman-Hill says tho, Scala does this for you (as I understand it, this is how it implements traits on the JVM).




回答3:


I know you said "pure Java", but this is something Scala does well. Limitations in the Java language itself are a strong driver for people to adopt other JVM languages...




回答4:


In case you consider using lombok as pure Java, you could simplify your life by using @Delegate like this:

public class SomeObject implements Updatable, Loadable {
    @Delegate private final Updatable updatable = new DefaultUpdatable();
    @Delegate private final Loadable loadable = new DefaultLoadable();
}


来源:https://stackoverflow.com/questions/7152027/ways-to-achieve-effective-java-traits

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!