代码之家  ›  专栏  ›  技术社区  ›  Jay Haase

仅类及其子类的属性

  •  20
  • Jay Haase  · 技术社区  · 14 年前

    是否可以定义仅对在其中定义的类和该类的子类可用的属性?

    换句话说,是否有定义受保护属性的方法?

    3 回复  |  直到 11 年前
        1
  •  15
  •   Dave DeLong    14 年前

    从技术上讲,不是。属性实际上只是方法,所有方法都是公共的。我们在Objective-C中“保护”方法的方式是不让其他人知道它们。

    实际上,是的。您可以在类扩展中定义属性,并且仍然 @synthesize 它们在主实现块中。

        2
  •  10
  •   d4n3    11 年前

    这可以通过使用一个类扩展名(不是category)来实现,该扩展名包含在基类和子类的实现文件中。

    类扩展名的定义类似于类别,但没有类别名称:

    @interface MyClass ()
    

    在类扩展中,可以声明属性,这样就可以合成支持ivar(XCode>4.4 ivar的自动合成也可以在这里工作)。

    在扩展类中,可以重写/优化属性(将readonly更改为readwrite等),并添加对实现文件“可见”的属性和方法(但请注意,这些属性和方法不是真正私有的,仍然可以由选择器调用)。

    其他人建议使用单独的头文件MyClass_protected.h,但是也可以在主头文件中使用 #ifdef 这样地:

    例子:

    基类.h

    @interface BaseClass : NSObject
    
    // foo is readonly for consumers of the class
    @property (nonatomic, readonly) NSString *foo;
    
    @end
    
    
    #ifdef BaseClass_protected
    
    // this is the class extension, where you define 
    // the "protected" properties and methods of the class
    
    @interface BaseClass ()
    
    // foo is now readwrite
    @property (nonatomic, readwrite) NSString *foo;
    
    // bar is visible to implementation of subclasses
    @property (nonatomic, readwrite) int bar;
    
    -(void)baz;
    
    @end
    
    #endif
    

    基类.m

    // this will import BaseClass.h
    // with BaseClass_protected defined,
    // so it will also get the protected class extension
    
    #define BaseClass_protected
    #import "BaseClass.h"
    
    @implementation BaseClass
    
    -(void)baz {
        self.foo = @"test";
        self.bar = 123;
    }
    
    @end
    

    儿童班.h

    // this will import BaseClass.h without the class extension
    
    #import "BaseClass.h"
    
    @interface ChildClass : BaseClass
    
    -(void)test;
    
    @end
    

    儿童班

    // this will implicitly import BaseClass.h from ChildClass.h,
    // with BaseClass_protected defined,
    // so it will also get the protected class extension
    
    #define BaseClass_protected 
    #import "ChildClass.h"
    
    @implementation ChildClass
    
    -(void)test {
        self.foo = @"test";
        self.bar = 123;
    
        [self baz];
    }
    
    @end
    

    当你打电话 #import ,它基本上是将.h文件复制粘贴到要导入的位置。 如果你有一个 #ifdef公司 ,它只在 #define 用那个名字命名。

    在.h文件中,不设置定义,因此任何导入此.h的类都不会看到受保护的类扩展名。 在基类和子类.m文件中,使用 #定义 使用前 #进口 这样编译器将包含受保护的类扩展。

        3
  •  0
  •   Arietis    12 年前

    您可以在子类实现中使用这种语法。

    @interface SuperClass (Internal)
    
    @property (retain, nonatomic) NSString *protectedString;
    
    @end
    
        4
  •  0
  •   Chung Mai    5 年前

    你可以使用一个类别来达到你的目的

    @interface SuperClass (Protected)
    
    @property (nonatomic, strong) UIImageView *imageView;
    @property (nonatomic, strong) UIView *topMenuView;
    @property (nonatomic, strong) UIView *bottomMenuView;
    
    @end
    

    在子类中,将该类别导入到文件中 .m.公司