一个实现:两个可能的超类 - 最干净的方法?

时间:2012-10-26 03:55:25

标签: iphone objective-c inheritance mkmapview mkannotationview

我正在研究一个模块,将自定义注释放在MKMapView上。我的大部分逻辑目前都在一个继承自MKAnnotationView的类中。我手动将所有相同的代码复制并粘贴到另一个继承自MKPinAnnotationView的类中,因此客户端地图委托可以使用自定义子类,具体取决于他们是否需要默认的图钉/动画。

为了使这段代码更易于维护/调试,我很想干掉这段代码并让我的自定义类继承自同一个类。但是,我还没有找到适当的方法来实现这个继承图:

CustomAnnotationView              CustomPinAnnotationView
            \                       /
             \                     /
              V                   V
        CustomBaseAnnotationImplementation
            /                      \
           /                        \
          V                          V
 MKAnnotationView              MKPinAnnotationView

我尝试过这样的事情:

#if UsesPinAnnotationView
#define CustomStandInSuperClass MKPinAnnotationView
#else
#define CustomStandInSuperClass MKAnnotationView
#endif

@interface CustomBaseAnnotationViewImplementation : CustomStandInSuperClass

然后将#define UsesPinAnnotationView 0放入我的CustomPinAnnotationView中的CustomAnnotationView#define UsesPinAnnotationView 1,并且没有一个像我想的那样工作(我认为它只是使用了第一个#define预处理器来了并且丢弃了另一个#define - 最后它在所有情况下使它成为MKAnnotationView子类并且我的代码成功编译,但随后在unrecognizedSelector上崩溃(setAnimatesDrop:)

我一直在研究使用ObjC Runtime API在运行时从常用实现文件中向我的具体子类添加方法,但这似乎不是一个可行(或必要)的解决方案。

所以,这不是多重继承......它是变量继承。似乎可以在不绕过框架约束的情况下执行某些操作。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

你是对的:对于那些能够提供更好解决方案的东西来说,对运行时等进行攻击并不是一个好主意。

通过使用组合而不是继承,您可以将所有可重用逻辑隔离到每个类将包含的另一个类中:

CustomAnnotationView              CustomPinAnnotationView
     /      \                        /       \
    /       has a                 has a       \
 is a          V                   V          is a
   \    CustomBaseAnnotationImplementation     /
    \                                         /
     \                                       /
      V                                     V
 MKAnnotationView <----is a -- MKPinAnnotationView

或者,在惯用目标-C中执行此操作的另一种方法是在MKAnnotationView上使用一个类别来定义您的自定义逻辑/动画/ hoo-hah,其头部导入到CustomAnnotationView和CustomPinAnnotationView的实现中。这充分利用了MKPinAnnotationView只是一个奇特的MKAnnotationView这一事实,因此这两种方法都可以使用这些方法。

这有帮助吗?

答案 1 :(得分:0)

您正在组合两种不同的预处理程序指令方法。

其中任何一个都适合你:

// Method 1:

#define UsesPinAnnotationView
// or #undef UsesPinAnnotationView

#ifdef UsesPinAnnotationView
#define CustomStandInSuperClass MKPinAnnotationView
#else
#define CustomStandInSuperClass MKAnnotationView
#endif

// Method 2:

#define UsesPinAnnotationView (1) // or 0 instead of 1

#if(UsesPinAnnotationView)
#define CustomStandInSuperClass MKPinAnnotationView
#else
#define CustomStandInSuperClass MKAnnotationView
#endif

但请注意,虽然这会解决您遇到的问题,但还有更好的方法(正如@AndrewPouliot建议的那样,合成将是一个非常好的选择)。