2011-08-22 9 views
6

El documento de Apple citado más adelante parece indicar que esto es permisible, aunque admitiré que nunca tengo una razón para hacerlo en una subclase hasta ahora.¿Por qué el compilador advierte al redeclar la propiedad readwrite de la clase base como readonly en la subclase?

Tengo una clase base con una propiedad de lectura pública y una subclase donde redeclaro la propiedad como de solo lectura. La subclase también tiene una extensión de clase que nuevamente redeclara la propiedad como readwrite para lograr el patrón común Objective-C "readonly público, privado". Sin embargo, me sale el siguiente advertencia del compilador:

warning: Semantic Issue: Attribute 'readonly' of property 'foo' restricts attribute 'readwrite' of property inherited from 'Base' 

estoy usando Xcode 4.1 build 4B110 con LLVM 2.1 (aunque LLVM GCC4.2 y GCC4.2 dan la misma advertencia) en 10,7.

Aquí está un ejemplo reducidos al mínimo, donde se expone la advertencia del compilador:

#import <Foundation/Foundation.h> 

@interface Base : NSObject 
@property (nonatomic, readwrite) BOOL foo; 
@end 

@implementation Base 
@dynamic foo; 
@end 

// Subclass 
@interface Sub : Base 
@property (nonatomic, readonly) BOOL foo; 
@end 

// Class extension 
@interface Sub() 
@property (nonatomic, readwrite) BOOL foo; 
@end 

@implementation Sub 
@dynamic foo; // it warns with @synthesize as well 
@end 

He aquí un pasaje relevante de The Objective-C Programming Language de Apple:

Propiedad redeclaración

Puede redeclare una propiedad en una subclase, pero (con la excepción de solo lectura contra lectura) debe repetir sus atributos en total en t él subclases. Lo mismo se aplica a una propiedad declarada en una categoría o protocolo , mientras que la propiedad se puede volver a declarar en una categoría o protocolo, los atributos de la propiedad deben repetirse en su totalidad.

Si se declara una propiedad en una clase como de sólo lectura, puede redeclare que como lectura-escritura en una extensión de clase (ver “Extensiones”), en un protocolo o en una subclase (ver “La subclasificación con propiedades”) . En el caso de una redeclaración de extensión de clase , el hecho de que la propiedad se volvió a declarar antes a cualquier instrucción @synthesize hace que el sintetizador sea sintetizado. La capacidad de redeclarar una propiedad de solo lectura como de lectura/escritura habilita dos patrones de implementación comunes : una subclase mutable de una clase inmutable (NSString, NSArray y NSDictionary son todos ejemplos) y una propiedad que tiene una API pública que es de solo lectura pero una implementación de lectura privada interna a la clase. El siguiente ejemplo muestra el uso de una extensión de clase para proporcionar una propiedad que se declara como de solo lectura en el encabezado público pero se redeclara de forma privada como lectura/escritura.

Declaro públicamente las propiedades de solo lectura readwrite en las extensiones de clase todo el tiempo, pero creo que nunca he tenido motivos para hacerlo una subclase. Sin embargo, a menos que lo esté leyendo mal, los párrafos anteriores parecen indicar que es kosher. ¿Alguien me puede aclarar y/o conciliar el aparente conflicto entre los documentos y el compilador?

¿Por qué quiero hacer esto? Mi situación en el mundo real es más compleja, por supuesto. Puedo hacer cambios de diseño para evitar esto, si es necesario, pero esta parecía ser la alternativa de menor fricción (la necesidad de hacer esto es impulsada por otros cambios).

Respuesta

10

Dice que puede redeclarar una propiedad readonly como readwrite pero está haciendo lo contrario.No se puede/no debe hacerlo porque es posible hacer esto:

Sub* s = [[[Sub alloc] init] autorelease]; 
Base* b = s; 
b.foo = YES; //legal for `Base` objects, but not legal for `Sub` objects 

Es una violación de la the Liskov Substitution Priciple.

+0

Lo que dijo Tom. No tiene sentido hacer una subclase de solo lectura cuando la superclase ofrece readwrite públicamente. En general, agrega mutabilidad bajando por la jerarquía de clases (consulte los diversos ejemplos de grupos de clases Immutable -> Mutable proporcionados en el sistema operativo). – bbum

+0

Gracias Tom y bbum. Yo (debería) saber mejor. Creo que pasé demasiado tiempo este fin de semana reflexionando sobre mi problema real y perdí de vista los primeros principios. Incluso tuve una segunda oportunidad de atraparme, pero mi cerebro de alguna manera se filtró "o en una subclase" en el segundo párrafo del documento a través de múltiples lecturas. Después de un descanso para cenar y volviendo a tus respuestas, me siento un poco tonto con esto. Gracias por su claridad, ¡y disfruté el enlace de Liskov! – Slipknot

Cuestiones relacionadas