Java 是否可以使用“优化密封类?”;密封方法;?

Java 是否可以使用“优化密封类?”;密封方法;?,java,java-15,java-sealed-type,Java,Java 15,Java Sealed Type,我正在玩Java15中的预览密封类,我想知道为什么关键字sealed和non-sealed只适用于类和接口,而不适用于方法(就像其他修饰符一样)。我想具体决定哪些方法可以被允许的子类覆盖可能会很有用 例如:我有一个类Unit,它有两个子类Metric和Imperial,这两个子类最终都实现了一个基本功能,这里是kind() 这很有效。但是,现在我不想在所有子类中实现kind(),而是提供一个对所有子类都是最终的实现,但允许重写的子类除外。在我看来,这应该是这样的: public abstract

我正在玩Java15中的预览密封类,我想知道为什么关键字
sealed
non-sealed
只适用于类和接口,而不适用于方法(就像其他修饰符一样)。我想具体决定哪些方法可以被允许的子类覆盖可能会很有用

例如:我有一个类
Unit
,它有两个子类
Metric
Imperial
,这两个子类最终都实现了一个基本功能,这里是
kind()

这很有效。但是,现在我不想在所有子类中实现
kind()
,而是提供一个对所有子类都是最终的实现,但允许重写的子类除外。在我看来,这应该是这样的:

public abstract sealed class Unit permits Imperial, Metric {
    // this is not supported
    public sealed String kind () permits Imperial {return "easy"; }
}

public abstract non-sealed class Imperial extends Unit {
    @Override
    public final String kind() { return "oh my god"; }
}

public abstract non-sealed class Metric extends Unit {
    // should not be possible to override kind() here or in any subclass
}

是否有任何方法可以通过新功能实现这一点,或者我缺少任何其他方法?

您可以通过包访问类实现这一点

将所有三个类都放在它们自己的包中,并将
kind()
委托给包私有方法,即既不是公共的,也不是受保护的,也不是私有的方法。这将只允许该包中的类重写它:

package com.example.units;

public abstract sealed class Unit permits Imperial, Metric {
    public final String kind () {
        return kindImpl();
    }

    String kindImpl() { return "easy"; }
}

package com.example.units;

public abstract class Imperial extends Unit {
    @Override
    String kindImpl() { return "imperial"; }
}
kindImpl()
是包私有的,因此只有同一包中的类才能重写它


这适用于任何版本的Java,无论是否使用密封类。

是,按规程。密封这个类意味着你可以控制所有的实现,所以你不需要对其他实现者采取额外的预防措施,因为这是你的全部。当然,这是正确的。但是,如果方法在单元中是抽象的,那么实现可能会有些冗余。如果不是,我必须在每个允许的类中重写它,以确保它对于其他子类是最终的。即使有纪律,这也可能会在一段时间后被扩展到雷达之下。我认为这个解决方案解决了上面的例子,但是当有更多不同需求的方法时,可能会变得困难involved@achim如果要将方法限制为覆盖不同包中的特定类,我认为你的设计可能需要重新思考。这个问题并没有说明任何不同的软件包,但是是的,如果我真的有问题需要这样做,我可以提出不同的设计。我只是想知道为什么没有为方法定义密封功能(我只是尝试探索)。从这些评论中,我理解“因为我们永远不会需要它”。不完全确定这是不是真的…@achim我想你被卡住的地方是“好处可能不是零”不是判断语言特性的合适标准。每一个特性都增加了复杂性,并且有机会成本;执行功能X意味着我们不执行功能Y。因此,“收益非零”不是标准(甚至也不是“收益与成本一致”,除非你有无限的能力)。在这里,收益微乎其微,可以忽略不计,因此它甚至不会被排除在外。(你真的不想用一种语言编写程序,这种语言拥有某个人、某个地方认为有用的所有功能。)
package com.example.units;

public abstract sealed class Unit permits Imperial, Metric {
    public final String kind () {
        return kindImpl();
    }

    String kindImpl() { return "easy"; }
}

package com.example.units;

public abstract class Imperial extends Unit {
    @Override
    String kindImpl() { return "imperial"; }
}