5

I am attempting to create an abstract class and inherit some of its properties in a subclass. If I leave the properties in the abstract class' header file, all of the properties are accessible. The problem is that the instance of the subclass can also access those properties, which is not always desirable in my case.

For instance, I have a delegate in my abstract class that sends down button presses to its sub class. I realize that this may not be the best way of structuring inheritance, so other suggestions are welcome. However, I would still like to know how my subclass can inherit some properties from its superclass without making all of those properties available in its instance. Thanks in advance!

Here is some example code below:

@interface AbstractClass : UIView

@property (nonatomic, strong) id<ButtonDelegate>buttonDelegate;

@end

…

@protocol ButtonDelegate

@required
- (void) buttonWasPressed;

@end

…

@interface SubClass() <ButtonDelegate>

- (id)init {
    self = [super init];
    if (self) {
        self.buttonDelegate = self;
    }
    return self;
}

-(void) buttonWasPressed {
    [self doSomething];
}

…

@implementation ViewController

- (void)viewDidLoad {
    SubClass *subClass = [[SubClass alloc] init];
    subClass.buttonDelegate = self; // THIS IS NOT DESIRABLE
}
4

6 回答 6

4

Do like UIGestureRecognizer does.

  1. All public properties and methods goes into UIGestureRecognizer.h

  2. All protected properties and methods goes into UIGestureRecognizerSubclass.h. Only import this in the *.m-files. Never include it in any public header.

  3. All private properties and methods goes into *.m-files. Use the @interface ClassName ()

Example https://gist.github.com/hfossli/8041396

于 2013-10-11T15:28:06.277 回答
3

如何我的子类可以从其超类继承一些属性,而无需在其实例中提供所有这些属性

这有什么问题?

#import <Foundation/Foundation.h>

@interface Animal : NSObject
{
    @protected
    NSString *name; // default access. Only visible to subclasses.
}
@end

@implementation Animal
-(NSString*)description {
    return name;
}
@end

@interface Cow : Animal
@end

@implementation Cow

-(id)init {
    self=[super init];
    if (self){
        name   = @"cow";
    }
    return self;
}
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        Cow *cow = [Cow new];
        NSLog(@"%@", cow); // prints the name through internal access
        // error accessing from the outside: NSLog(@"%@", cow.name);

        Animal *animal = [Animal new];
        // error accessing from the outside: NSLog(@"%@", animal.name);
    }
}

也许我误解了这个问题,你说

在Objective-C中创建仅对子类可见的属性

接着

问题是子类的实例也可以访问那些属性

哪一个?

于 2013-10-11T15:48:10.920 回答
1

我认为没有任何方法可以使用属性声明来实现这一点。

一个属性要么对所有人可见(在 .h 文件中声明),要么对所有人不可见(在 .m 文件中使用类别声明)

我想一种方法是在 .h 文件类声明中声明公共/受保护变量:

@interface AbstractClass : UIView {

   ...

   id<ButtonDelegate>buttonDelegate;

   ...
}
@end

我不确定这一点,但试一试。

于 2013-10-11T15:04:34.117 回答
1

我看到一种可以解决您的问题的方法,但是,它非常粗鲁。使用 Antonio 的建议并使用该属性创建私有类别。正如您所提到的,它的范围仅限于 .m 文件。所以你可以把你的子类放到那个文件中。如果子类很大,这将很难阅读代码,但据我所知,这是您的唯一方法。

编辑:好吧,我有另一个解决方案。复制

@property (nonatomic, strong) id<ButtonDelegate>buttonDelegate;

到你所有的子类。这会给你一个关于属性缺失的警告@synthesize,但应该可以工作。如果不经常更改或添加子类,我更喜欢这个。

让我描述一下它是如何工作的。

我们在 Abstract 类中添加一个属性,它对所有人(甚至对子类)都是隐藏的:

// .m file

@interface Abstract ()

@property (nonatomic, strong) id<ButtonDelegate> buttonDelegate;

@end


@implementation Abstract

@synthsize buttonDelegate;

@end;

但是由于 Objective-C 的运行时特性,我们仍然可以调用该属性,并且不会出现任何运行时错误,只有编译器警告。

为了消除该警告并添加自动完成功能,我们将不带 @synthsize 的属性添加到所有子类中:

@interface MySubclass : Abstract

@property (nonatomic, strong) id<ButtonDelegate> buttonDelegate;

@end

这将告诉编译器某处有这样的属性。还有一个关于没有@synthesize 的警告,但是如果你写类似的东西,Xcode 仍然可以自动完成

MySubclass *subclass = ...
subclass.butto...
于 2013-10-11T15:31:30.027 回答
1

在您的实现文件 (.m) 之上创建一个空类别:

@interface AbstractClass()

@property (nonatomic, strong) id<ButtonDelegate>buttonDelegate;

@end

这样,您的子类将继承并可以访问该属性,但不能访问其他外部类,因为它不在标头中。

于 2013-10-11T14:49:42.340 回答
0

这是不可能的。在objective-c 中没有private 或protected。在 .m 文件“私有”接口中声明的内容仅对该类可见,而在任何子类中均不可见。如果您愿意,您也可以随时从外部使用您的“私有”属性/方法,尽管这样做是不好的做法。

于 2013-10-11T15:23:26.253 回答