Java 接口中的可选方法

Posted

技术标签:

【中文标题】Java 接口中的可选方法【英文标题】:Optional method in Java Interface 【发布时间】:2011-07-13 18:37:54 【问题描述】:

我有一个包含多个方法定义的接口,我希望需要其中的一些。

这可能吗?如果是这样,我该如何实现?

我尝试设置@Optional 的注释,但这似乎不起作用。

我必须在某处定义Optional 注释吗?

【问题讨论】:

听起来你需要创建几个接口 - 从概念上讲,如果你不能依赖它提供的合约,接口有什么好处。 这完全破坏了界面的全部意义。除非您希望编译器通过检查所有实现的覆盖来决定接口是否应该在编译时具有该方法.... 不,坏主意 @Spidy -- 我认为它没有。具有可选接口方法的模式在 Objective-C 中非常普遍且非常有效地使用。可选方法可以只是 No-op。 正是我想要完成的。我喜欢在 cocoa-touch/objective-c 中我可以指定 @optional@required 并在调用它之前测试对象是否响应这些方法 我想这是有道理的,因此您不必提供执行默认空行为的抽象实现 【参考方案1】:

Java 中没有 @Optional 注释。您可以做的一件事是创建一个接口,然后创建一个提供存根实现的抽象类。然后,您的类可以扩展这个基类并覆盖他们感兴趣的方法。

【讨论】:

为什么要用抽象类来实现接口?不能用普通类来实现吗?【参考方案2】:

你可以有一个抽象类,用空函数实现实现这个接口,然后从抽象类扩展

话虽如此,我会质疑您为什么需要这样做。也许您需要将接口拆分为多个较小的接口并实现类所需的唯一接口

【讨论】:

例如java.awt.event.MouseAdapter 为什么要用抽象类来实现接口?不能用普通类来实现吗? @MartinChekurov 您也可以使用普通类执行此操作,但您的代码的用户将能够实例化它。如果这不是问题,那当然!我想让它保持抽象,以确保人们明白在它完全被使用之前他们还有工作要做。【参考方案3】:

虽然我同意其他答案,但应该注意 JDK 中存在此类可选方法。例如,List.add() 是可选的。如果不想实现此方法,实现必须抛出 UnsupportedOperationException。

如果您想知道可选方法是否实现,那么您可以添加另一个方法(非可选):

/**
 * Returns true if optionalOperation() is supported and implemented, false otherwise
 */
boolean isOptionalOperationSupported();

/**
 * implements he foobar operation. Optional. If not supported, this method must throw
 * UnsupportedOperationException, and isOptionalOperationSupported() must return false.
 */
void optionalOperation();

【讨论】:

【参考方案4】:

“从概念上讲,如果你不能依赖它提供的合约,那么接口有什么好处”,Erik 说。

确实如此,但还有其他考虑:人们可以期望符合接口中包含的某些属性或方法的不同类的对象通过测试实现了哪些属性或方法来安全地处理它们。

这种方法经常在 Objective-C 或 Swift Cocoa 中遇到,其“协议”(相当于“接口”)允许将属性或方法定义为“可选”。

可以测试对象实例以检查它们是否符合专用协议。

// Objective C

[instance conformsToProtocol:@protocol(ProtocolName)] => BOOL

// Swift (uses an optional chaining to check the conformance and the “if-let” mech)

if let ref: PrototocolName? = instance  => nil or instance of ProtocolName

可以检查方法的实现(包括getter和setter)。

// Objective C

[instance respondsToSelector:@selector(MethodName)] => BOOL


// Swift (uses an optional chaining to check the implementation)

if let result = instance?.method…

该原则允许使用方法取决于它们在未知对象中的实现但符合协议。

 // Objective C: example

if ([self.delegate respondsToSelector:@selector(methodA:)]) 
      res = [self.delegate methodA:param];

 else if ([self.delegate respondsToSelector:@selector(methodB)]) 
      res = [self.delegate methodB];

 …

 // Swift: example

 if let val = self.delegate?.methodA?(param) 
      res = val
 else if let val = self.delegate?.methodB 
      res = val
 …

JAVA 不允许在界面中设置“可选”项,但由于界面扩展,它允许执行非常相似的操作

interface ProtocolBase 
interface PBMethodA extends ProtocolBase 
    type methodA(type Param);

interface PBMethodB extends ProtocolBase 
    type methodB();


 // Classes can then implement one or the other.

class Class1 implement PBMethodA 
    type methodA(type Param) 
    …
    

class Class2 implement PBMethodB 
    type methodB() 
    …
    

然后可以将实例作为 ProtocolBase 的“实例”进行测试,以查看对象是否符合“通用协议”和“子类协议”之一,以选择性地执行正确的方法。

虽然委托是 Class1 或 Class2 的实例,但它似乎是 ProtocolBase 的实例和 PBMethodA 或 PBMethodB 的实例。所以

if (delegate instance of PBMethodA) 
    res = ((PBMethodA) delegate).methodA(param); 

 else if (dataSource instanceof PBMethodB) 
    res = ((PBMethodB) delegate).methodB();

希望这会有所帮助!

【讨论】:

... else if (delegate instanceof PBMethodB) ... 我猜?

以上是关于Java 接口中的可选方法的主要内容,如果未能解决你的问题,请参考以下文章

FlutterDart的方法中的可选参数方法作为参数传递

JavaScript中的可选参数[重复]

Spring boot:Query方法中的可选参数查询

抽象方法中的可选参数?可能吗?

在模板基类中为继承类中的可选覆盖生成虚拟方法

应该在哪里定义我的可选 DefaultTableModel 方法?