【问题标题】:Is there a way to allow certain classes to access private properties of certain other classes?有没有办法允许某些类访问某些其他类的私有属性?
【发布时间】:2013-03-26 14:09:20
【问题描述】:

我有 2 个类希望能够访问彼此的属性,但我不希望从其他任何地方访问这些属性。有没有办法做到这一点?是通过子类化来实现这一点的唯一方法吗?有没有办法在两个类之间建立“特殊”关系?

【问题讨论】:

    标签: ios objective-c scope encapsulation private-members


    【解决方案1】:

    如果我理解您的问题,您实际上希望与继承无关的 A 类和 B 类了解比公开宣传更多的内部信息吗?

    假设 A 有一个名为 innardsForB 的属性,只有 B 的实例才能访问该属性。您可以使用类扩展来声明 A 的非公共接口。


    啊.h
    @interface A:NSObject
    ... regular class goop here ...
    @end
    


    A-Private.h
    @interface A()
    @property(nonatomic, strong) Innards *innardsForB;
    @end
    


    上午
    #import "A.h"
    #import "A-Private.h"
    
    @implementation A
    // because "A-Private.h" is #import'd, `innardsForB` will be automatically @synthesized
    ...
    @end
    


    B.m
    #import "B.h"
    #import "A-Private.h"
    
    @implementation B
    ...
    - (void)someMethod
    {
         A *a = [self someASomewhere];
         a.innardsForB = [[Innards alloc] initForMeaning:@(42)];
    }
    

    【讨论】:

    • 在这个例子中 A-Private.h 是类扩展?
    • 正确; @interface A() 是类扩展。它的意思是“扩展 A 类,使其具有这组额外的声明”。只要在编译 @implementation 时该扩展对编译器可见,那么扩展中的所有声明的行为就像它们在类的 @interface 中声明的一样。
    【解决方案2】:

    协议就是为此目的而设计的。您不能阻止 3rd 方类实现或使用协议。其中的方法是公共的,但不一定是公共接口的一部分。

    【讨论】:

      【解决方案3】:
      【解决方案4】:

      我希望 classA 访问 classB 的属性,而 classC 不是简单地在 ClassB 中声明 classA 的引用而不在 ClassB 中声明它。

      例子:

      @interface ClassA
      @property (nonatomic, strong) UILabel *label1;
      @end
      
      #import "ClassB.h"
      #import "ClassA.h"  // To access public properties and all methods declared in ClassA.h
      
      @implementation ClassB 
      
      ClassA *classA = ....;
      classA.label1.text = ...;
      
      @end 
      

      从这个例子中,ClassB 可以访问 ClassA 的所有公共(在 CalssA.h 中声明的)属性和方法。

      您也可以使用委托来执行此操作。

      【讨论】:

      • 这是一种信息重复,会导致代码库的脆弱性。您现在必须记住始终在您的代码中搜索每个属性的所有重新声明,以防它在其他地方重复。
      【解决方案5】:

      在 obj-c 上的属性受到保护。这意味着您只能通过继承来获得属性。

      @interface A : NSObject{
          NSObject* prop;
      }
      @end
      
      @implementation A
      @end
      
      @interface B : A
      @end
      
      @implementation B
      - (void)protected{
          self->prop; // yep
      }
      @end
      
      @interface XXX : NSObject
      @end
      
      @implementation XXX
      
      - (void)test{
          A* a = [[A alloc] init];
          a->prop; // wrong, will not compile
      }
      
      @end
      

      如果你想通过方法访问隐藏的属性,你可以使用简单的实现中隐藏的类别,或者桥接。但是没有办法在两个类之间建立“特殊”关系。但是您可以在代码设计中强制执行这种关系。

      【讨论】:

      • 您的代码中没有属性,使用-> 会破坏封装。
      • prop 是一个实例变量,与 ObjC 中具有非常特殊含义的属性有很大不同。使用一个类别来访问另一个类中的“隐藏”功能是一个糟糕的建议;正如我在回答中概述的那样,创建类扩展正是为了解决这个问题,它正是为了创建这种“特殊”关系。
      • @MrBonjour 你应该知道 bbum 是谁。然后,您将了解您的评论的欢闹。 :)
      • 实际上,@property 还定义了 -- 综合 -- 支持 setter/getter 的存储。因此,Obj-C 中的属性完全替代了 ivars(除了遗留运行时之外的所有)。建议直接或通过performSelector: 调用隐藏方法在调试或完全绝望之外是一个非常糟糕的主意。
      • @samir,bbum 为 Apple 工作。 “Bill Bumgarner 是 Apple 的一名工程经理。他管理着负责 Objective-C 和相关技术的运行时技术团队。”来源:newtonacademy.org/resources/ios-rockstars我很确定他知道什么是属性。
      猜你喜欢
      • 2011-02-23
      • 2013-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多