Optional method in Java Interface
Asked Answered
P

4

24

I have an interface with several method definitions, and I would not like to require some of them.

Is this possible? if so, how can i implement this?

I have tried setting an annotation of @Optional but this doesn't seem to work.

Do i have to define the Optional annotation somewhere?

Procrustean answered 11/3, 2011 at 20:34 Comment(6)
Sounds like you need to make several interfaces - Conceptually, what good is an interface if you cannot rely on the contract it provides.Federation
This completely undermines the whole point of an interface. Unless your looking to have the compiler decide if the interface should have the method at compile time by checking all implementations for overrides.... Ya no, bad ideaRutaceous
@Rutaceous -- I would argue it does not. The pattern of having optional interface methods is used very commonly and quite effectively in Objective-C. Optional methods can just be No-op.Sherysherye
exactly what i'm trying to accomplish. i like how in cocoa-touch/objective-c i can just specify @optional or @required and test if a object responds to such methods before calling itProcrustean
i guess that makes sense so that you don't have to supply an abstract implementation that does a default null behaviorRutaceous
I agree with your original standpoint, Spidy. I have experience in both Java and Objective-C, and I view "Java interfaces" and "Objective-C @interfaces" quite differently. They are not 1-to-1 analogous in my opinion. The Objective-C counterpart more resembles classes with (pure) virtual methods in C++ rather than interfaces in Java, in my opinion.Concomitance
B
8

Although I agree with the other answers, one should note that such optional methods exist in the JDK. For example, List.add() is optional. Implementations must throw an UnsupportedOperationException if they don't want to implement this method.

If you want to be able to know if the optional method is implemented or not, then you could add another method (not optional) :

/**
 * 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();
Blindage answered 11/3, 2011 at 21:1 Comment(0)
P
24

There is no @Optional annotation in Java. One thing you can do is to create an interface, and then create an abstract class that provides stub implementations. Your classes can then extend this base class and override the methods they are interested in.

Proffer answered 11/3, 2011 at 20:36 Comment(1)
Why implement the inteface with an abstract class?Can't i just implement with with a normal class?Counts
C
14

You can have an Abstract class that implements this interface with empty function implementations and then extend from the Abstract class

Having said that, I would question why you need to do this. Maybe you need to split you interface into multiple smaller ones and implement the only ones that you need for a class

Casuist answered 11/3, 2011 at 20:37 Comment(3)
An example of this is java.awt.event.MouseAdapterNaarah
Why implement the inteface with an abstract class?Can't i just implement with with a normal class?Counts
@MartinChekurov You can do this with a normal class as well, but users of your code will be able to instantiate it. If that's not a problem, then sure! I'd like to keep it abstract to make sure people understand that they still have work to do before it can be used fully.Casuist
B
8

Although I agree with the other answers, one should note that such optional methods exist in the JDK. For example, List.add() is optional. Implementations must throw an UnsupportedOperationException if they don't want to implement this method.

If you want to be able to know if the optional method is implemented or not, then you could add another method (not optional) :

/**
 * 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();
Blindage answered 11/3, 2011 at 21:1 Comment(0)
R
4

"Conceptually, what good is an interface if you cannot rely on the contract it provides" said Erik.

That's true but there is an other consideration: One can expect objects of different classes conforming to some properties or methods included in an interface to securely process with them by testing which properties or methods are implemented.

This approach can be frequently meet under Objective-C or Swift Cocoa for which the “protocol” — equiv of “interface” — allows to defined as “optional” a property or a method.

Instance of objects can be tested to check if they conform to a dedicated protocol.

// 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

The implementation of a method (including getter and setter) can be checked.

// Objective C

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


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

if let result = instance?.method…

The principle allows to use methods depending on their implementation in unknown objects but conforming to protocol.

 // 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 does not allow to make “optional” an item in an interface but it allows to do something very similar thanks to interface extension

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() {
    …
    }
}

Then instances can be tested as “instance of” both ProtocolBase in order to see if object conform to the “general protocol” and to one of the “subclassed protocols” to execute selectively the right method.

While delegate is instance of Class1 or Class2 it appears to be instance of ProtocolBase and either instance of PBMethodA or PBMethodB. So

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

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

Hope this helps!

Riser answered 18/5, 2016 at 22:37 Comment(1)
... else if (delegate instanceof PBMethodB) ... I guess?Wall

© 2022 - 2024 — McMap. All rights reserved.