Java 8 - 使用双冒号语法

时间:2015-06-10 19:19:15

标签: java inheritance lambda java-8

我正在深入研究Java 8的创新,我正在尝试调用我在高级接口中实现的默认方法,即使子类重写它也是如此。我可以毫不费力地回到Comparator课程中实现BusinessLogic,但我想知道是否有一些魔法可以让我使用漂亮的新::

代码:

public interface IdEntity extends Comparable<IdEntity> {

    int getId();

    @Override
    default int compareTo(IdEntity other) {
        return getId() - other.getId();
    }
}

public class Game implements IdEntity {
    @Override
    public int compareTo(IdEntity o) {
        if (o instanceof Game) {
            Game other = (Game) o;
            int something;
            // logic
            return something;
        }
        return super.compareTo(o);
    }
}

public class BusinessLogic {
    private void sortList(List<? extends IdEntity> list) {
        // for Game, Game::compareTo gets called but I want, in this call only, the default method
        Collections.sort(list, IdEntity::compareTo);
    }
}

3 个答案:

答案 0 :(得分:6)

一种方法是将compare方法放在静态方法中:

public static interface IdEntity extends Comparable<IdEntity> {
  int getId();
  @Override default int compareTo(IdEntity other) {
    return defaultCompare(this, other);
  }
  static int defaultCompare(IdEntity first, IdEntity second) {
    return first.getId() - second.getId();
  }
}

然后你的方法是:

Collections.sort(list, IdEntity::defaultCompare);

答案 1 :(得分:5)

更简单的方法:静态导入Comparator.comparingInt并使用

Collections.sort(list, comparingInt(IdEntity::getId));

我不相信你可以重新提取默认的compareTo实现:它被覆盖了;您通常无法运行重写方法实现。但这只会直截了当。

答案 2 :(得分:2)

一些一般性说明:

如果某个类重写了超类方法,则其他类无法有意调用超类方法,即忽略此方法已被覆盖的事实。禁止这种绕过是Java编程语言的基本设计决定。

唯一可以显式调用重写方法的类是执行覆盖的类,当然也只是在自身的实例上。因此,在Game.compareTo中,您可以使用IdEntity.compareTo调用被覆盖的IdEntity.super.compareTothis将调用super实例上的方法。

您也可以创建对此this调用的方法引用,但由于它仅在this实例上允许,因此Game实例必须绑定且不能是功能签名。例如。在ToIntFunction<IdEntity> f=IdEntity.super::compareTo; 的实例方法中,您可以写:

default

此函数将调用当前IdEntity.compareTo实例上的Game方法IdEntity,并通过abstract参数。

但整个设计应该受到质疑。您永远不应该创建一个类层次结构,其中覆盖了履行compareTo契约的非Comparable Comparator方法。这是一种反模式,会导致错误和令人惊讶的行为。作为Louis Wasserman has pointed out,可以轻松地为所需行为创建Game。如果IdEntity个实例的自然顺序与一般Comparator顺序不同,则其中至少有一个不是“自然顺序”,因此应仅表示为import java.util.Comparator; public interface IdEntity /* not Comparable<IdEntity> */ { int getId(); static Comparator<IdEntity> defaultOrder() { return Comparator.comparingInt(IdEntity::getId); } } ,甚至可能两者。

Game

如果您认为public class Game implements IdEntity,Comparable<Game> { public int compareTo(Game o) { int something; // logic return something; } // … } 拥有自然顺序

Game

或默认IdEntity.defaultOrder()订单只是import java.util.Comparator; public class Game implements IdEntity { public static Comparator<Game> defaultGameOrder() { return (a,b) -> { int something; // logic return something; }; } // … } 的替代选择:

<h1>Isotope - combination filters</h1>

<div class="filters">

<div class="ui-group">
<h3>Color</h3>
<div class="button-group js-radio-button-group" data-filter-group="color">
  <button class="button is-checked" data-filter="">any</button>
  <button class="button" data-filter=".red">red</button>
  <button class="button" data-filter=".blue">blue</button>
  <button class="button" data-filter=".yellow">yellow</button>
 </div>
 </div>

 <div class="ui-group">
 <h3>Size</h3>
<div class="button-group js-radio-button-group" data-filter-group="size">
  <button class="button is-checked" data-filter="">any</button>
  <button class="button" data-filter=".small">small</button>
  <button class="button" data-filter=".wide">wide</button>
  <button class="button" data-filter=".big">big</button>
  <button class="button" data-filter=".tall">tall</button>
</div>
</div>

<div class="ui-group">
<h3>Shape</h3>
<div class="button-group js-radio-button-group" data-filter-group="shape">
  <button class="button is-checked" data-filter="">any</button>
  <button class="button" data-filter=".round">round</button>
  <button class="button" data-filter=".square">square</button>
</div>
</div>

</div>

<div class="grid">
<div class="color-shape small round red"></div>
<div class="color-shape small round blue"></div>
<div class="color-shape small round yellow"></div>
<div class="color-shape small square red"></div>
<div class="color-shape small square blue"></div>
<div class="color-shape small square yellow"></div>
<div class="color-shape wide round red"></div>
<div class="color-shape wide round blue"></div>
<div class="color-shape wide round yellow"></div>
<div class="color-shape wide square red"></div>
<div class="color-shape wide square blue"></div>
<div class="color-shape wide square yellow"></div>
<div class="color-shape big round red"></div>
<div class="color-shape big round blue"></div>
<div class="color-shape big round yellow"></div>
<div class="color-shape big square red"></div>
<div class="color-shape big square blue"></div>
<div class="color-shape big square yellow"></div>
<div class="color-shape tall round red"></div>
<div class="color-shape tall round blue"></div>
<div class="color-shape tall round yellow"></div>
<div class="color-shape tall square red"></div>
<div class="color-shape tall square blue"></div>
<div class="color-shape tall square yellow"></div>
</div>