【问题标题】:Is it possible to refine sealed classes with "sealed methods"?是否可以使用“密封方法”来改进密封类?
【发布时间】:2020-12-02 10:57:15
【问题描述】:

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

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

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

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

public abstract non-sealed class Metric extends Unit {
    @Override
    public final String kind() { return "metric"; }
}

这行得通。但是,现在我不想在所有子类中实现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
}

我有什么方法可以通过新功能实现这一点,或者我还缺少其他方法吗?

【问题讨论】:

  • 是的,按纪律。密封类意味着您可以控制所有实现,因此您不需要针对其他实现者进行额外的预防,因为它就是您的全部。
  • 当然,这是正确的。但是,如果该方法在 Unit 中是抽象的,则实现可能会有些多余。如果不是,我必须在每个允许的类中覆盖它,以确保它对于进一步的子类是最终的。即使有纪律,这可能会在一段时间后的扩展中受到关注。

标签: java java-15 java-sealed-type


【解决方案1】:

您可以使用包访问类来做到这一点。

将所有三个类放在它们自己的包中,并将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,无论是否使用密封类。

【讨论】:

  • 我认为这个解决方案解决了上面的例子,但是当涉及到更多不同要求的方法时可能会变得困难
  • @achim 如果你想限制不同包中的特定类重写的方法,我认为你的设计可能需要重新考虑。
  • 这个问题没有说明任何关于不同包的内容,但是是的,如果我真的有需要这个的问题,我可以想出不同的设计。我只是想知道为什么没有为方法定义密封功能(我只是想探索)。从 cmets 我理解“因为我们永远不需要它”。不完全确定这是不是真的……
  • @achim 我认为你陷入困境的地方是“好处可能不是零”不是判断语言功能的合适标准。每个功能都会增加复杂性并具有机会成本;做特征 X 意味着我们不做 Y。所以“收益非零”不是标准(甚至,“收益与成本一致”也不是,除非你有无限的能力。)在这里,收益是如此微不足道,因为可以忽略不计,所以它甚至没有走出大门。 (你真的不想用一种语言编程,它具有某人在某个地方认为有用的所有功能。)
猜你喜欢
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 2020-02-16
  • 1970-01-01
  • 2021-12-15
  • 1970-01-01
  • 2018-05-11
相关资源
最近更新 更多