2011-03-11 24 views
20

Tengo una interfaz con varias definiciones de métodos, y me gustaría no como para requerir algunos de ellos.Método opcional en la interfaz Java

¿Esto es posible? si es así, ¿cómo puedo implementar esto?

He intentado establecer una anotación de @Optional pero esto no parece funcionar.

¿Debo definir la anotación Optional en alguna parte?

+9

Parece que tiene que hacer varias interfaces: en términos conceptuales, ¿de qué sirve una interfaz si no puede confiar en el contrato que proporciona? – Erik

+0

Esto socava por completo el punto de una interfaz. A menos que quiera que el compilador decida si la interfaz debe tener el método en tiempo de compilación, revise todas las implementaciones para anulaciones ... Ya no, mala idea – Spidy

+5

@Spidy - Yo diría que no. El patrón de tener métodos de interfaz opcionales se usa muy comúnmente y de manera bastante efectiva en Objective-C. Los métodos opcionales pueden ser No-op. – user491880

Respuesta

7

Aunque estoy de acuerdo con las demás respuestas, debe tenerse en cuenta que tales métodos opcionales existen en el JDK. Por ejemplo, List.add() es opcional. Las implementaciones deben lanzar una UnsupportedOperationException si no desean implementar este método.

Si usted quiere ser capaz de saber si se ejecuta o no el método opcional, entonces se podría añadir otro método (no opcional):

/** 
* 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(); 
21

No hay anotación @Optional en Java. Una cosa que puede hacer es crear una interfaz y luego crear una clase abstracta que proporcione implementaciones de stub. Sus clases se pueden extender esta clase base y anular los métodos que están interesados.

12

Usted puede tener una clase abstracta que implementa esta interfaz con las implementaciones de función vacías y luego se extienden desde la clase abstracta

Una vez dicho esto, Me preguntaría por qué necesitas hacer esto. Quizás necesite dividir su interfaz en varias más pequeñas e implementar las únicas que necesita para una clase

+1

Un ejemplo de esto es 'java.awt.event.MouseAdapter' –

3

"Conceptualmente, lo bueno es una interfaz si no puede confíe en el contrato que proporciona "dijo Erik.

Eso es cierto, pero hay otra consideración: se pueden esperar objetos de diferentes clases que se ajusten a algunas propiedades o métodos incluidos en una interfaz para procesarlos de forma segura probando qué propiedades o métodos se implementan.

Este enfoque se puede cumplir con frecuencia en Objective-C o Swift Cocoa para el cual el "protocolo" - equiv de "interfaz" - permite definir como "opcional" una propiedad o un método.

La instancia de los objetos se puede probar para comprobar si se ajustan a un protocolo dedicado.

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

Se puede verificar la implementación de un método (incluyendo getter y setter).

// Objective C 

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


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

if let result = instance?.method… 

El principio permite utilizar métodos que dependen de su implementación en objetos desconocidos pero que se ajustan al protocolo.

// 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 no permite hacer “opcional” en un elemento de una interfaz pero permite hacer algo gracias muy similares a la interfaz de extensión

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

Entonces casos pueden ser probados como “instancia de” ambos ProtocolBase para ver si el objeto se ajusta al "protocolo general" y a uno de los "protocolos subclase" para ejecutar selectivamente el método correcto.

Si bien delegate es una instancia de Class1 o Class2, parece ser una instancia de ProtocolBase y una instancia de PBMethodA o PBMethodB. Entonces

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

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

Hope this helps!

+0

... else if (instancia de delegado de PBMethodB) ... ¿Supongo? – Lemao1981

+0

Sí. Exacto. Gracias. –

Cuestiones relacionadas