IOS的多重继承

Reb*_*cca 12 protocols interface subclass multiple-inheritance ios

我想创建一个可以从两个自定义类继承的类.你有什么想法吗?请看下面我的例子:

头等舱:

@interface UIZoomableView : UIView
{
    UITapGestureRecognizer *_tapGestureRecognizer;
}
Run Code Online (Sandbox Code Playgroud)

和实施:

- (void)onDoubleTap:(UITapGestureRecognizer *)sender
{
    CGSize newSize;
    CGPoint centerPoint = self.center;
    if ([self isSmall])
    {
        newSize = [self bigSize];
    }
    else
    {
        newSize = [self smallSize];
    }

    [UIView animateWithDuration:0.3 animations:^{
        self.size = newSize;
        self.center = centerPoint;
    }];
}
Run Code Online (Sandbox Code Playgroud)

二等:

@interface UIDraggableView : UIView

    UIPanGestureRecognizer *_panGestureRecognizer;

@end
Run Code Online (Sandbox Code Playgroud)

执行:

- (void)handlePan:(UIPanGestureRecognizer*)sender
{
    ..
}
Run Code Online (Sandbox Code Playgroud)

我想创建一个可缩放和可拖动的自定义视图.你有什么想法吗?(没有复制代码..)

我认为类似协议,但我想要基类的默认值?我如何使用协议或类似协议来实现这一点.

谢谢你的回复!

Tri*_*ent 9

Objective-C不支持多重继承.您可以使用协议,组合和消息转发来实现相同的结果.

协议定义了一组对象必须实现的方法(也可以使用可选方法).组合基本上是包含对另一个对象的引用并在需要其功能时调用该对象的技术.消息转发是一种允许对象将消息传递到其他对象的机制,例如,通过合成包含的对象.

Apple参考:

因此,在您的情况下,Composition可能是一个解决方案,下面是示例代码

@interface ClassA : NSObject {
}

-(void)methodA;

@end

@interface ClassB : NSObject {
}

-(void)methodB;

@end

@interface MyClass : NSObject {
  ClassA *a;
  ClassB *b;
}

-(id)initWithA:(ClassA *)anA b:(ClassB *)aB;

-(void)methodA;
-(void)methodB;

@end

@implementation MyClass

-(id)initWithA:(ClassA *)anA b:(ClassB *)aB {
    a = anA ;
    b = aB ;
}

-(void)methodA {
    [a methodA] ;
}

-(void)methodB {
    [b methodB] ;
}

@end
Run Code Online (Sandbox Code Playgroud)

如果您不想在MyClass中实现ClassA和ClassB中的所有方法,则可以在MyClass中使用Message Forwarding来处理所有方法调用.只要ClassA和ClassB没有任何常用方法,下面的工作正常.

@implementation MyClass

-(id)initWithA:(ClassA *)anA b:(ClassB *)aB {
    a = anA ;
    b = aB ;
}

//This method will be called, when MyClass can not handle the method itself
-(void)forwardInvocation:(NSInvocation *)anInvocation
{
    if ([a respondsToSelector:[anInvocation selector]])
        [a invokeWithTarget:someOtherObject];
    else if ([b respondsToSelector:[anInvocation selector]])
        [b invokeWithTarget:someOtherObject];
    else
        [super forwardInvocation:anInvocation];
}

@end
Run Code Online (Sandbox Code Playgroud)


Ewa*_*lor 4

在 Objective C 中,最接近多重继承的是类别。这些是一种向已存在的类添加附加方法的机制。

请注意,这有一些重要的限制:

  1. 您不能使用类别添加属性或 ivars,但您可以使用关联对象来获得类似的效果;
  2. 编译器不会告诉您是否有在类和类别中或在两个类别中声明的同名方法,因此您必须小心避免名称冲突;
  3. 这不会显示为一个正确的类(因为 Objective C 没有多重继承),因此您的代码中不会有ScrollableZoomableView继承自ScrollableView和 的东西ZoomableView。这在 Objective C 中是不可能的(例如与 C++ 不同)。
  4. 将文件与类别链接时需要该标志,否则运行代码时-ObjC会出现错误;unrecognized selector
  5. 您无法在-initor期间调用代码+initialize,因为它们属于基类。您需要显式初始化您的属性。不过你仍然可以使用+load
  6. 您也无法拦截 dealloc,因此您可能也需要小心地显式取消注册侦听器。

你想要这样的东西:

@interface UIView (Zoomable)

@property (nonatomic) UITapGestureRecognizer * my_tapGestureRecognizer;

@end


@implementation UIView (Zoomable)

-(void)my_enableZooming() {
   self.my_tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(my_onDoubleTap:)];
   self.my_tapGestureRecognizer.numberOfTapsRequired = 2;
   [self addGestureRecognizer:self.my_tapGestureRecognizer];
}

-(void)my_disableZooming() {
   [self removeGestureRecognizer:self.my_tapGestureRecognizer];
   self.my_tapGestureRecognizer = nil;
}

-(void)my_onDoubleTap:(UITapGestureRecognizer *)sender {
    ...
}

-(UITapGestureRecognizer)my_tapGestureRecognizer {
    return objc_getAssociatedObject(self, @selector(my_tapGestureRecognizer));
}

-(void)setMy_tapGestureRecognizer:(UITapGestureRecognizer)value {
    objc_setAssociatedObject(self, @selector(my_tapGestureRecognizer), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end


@interface UIView (Draggable)

@property (nonatomic) UIPanGestureRecognizer * my_panGestureRecognizer;

@end

@implementation UIView (Draggable)

-(void)my_enableDragging() {
   self.my_panGestureRecognizer = ...;
}

-(void)my_disableDragging() {
    ...
}

-(void)my_handlePan:(UIPanGestureRecognizer*)sender {
    ...
}

-(UIPanGestureRecognizer)my_panGestureRecognizer {
    return objc_getAssociatedObject(self, @selector(my_panGestureRecognizer));
}

-(void)setMy_panGestureRecognizer:(UIPanGestureRecognizer)value {
    objc_setAssociatedObject(self, @selector(my_panGestureRecognizer), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end
Run Code Online (Sandbox Code Playgroud)