【问题标题】:Adding the same category to multiple classes将同一类别添加到多个类
【发布时间】:2012-03-16 01:44:03
【问题描述】:

我有一个 Objective-C 类别,我想将它添加到多个类中,而无需复制该类别中包含的代码。我只是想将相同的方法添加到多个类中。

我在 NSManagedObject 子类(BookChapterPage)上有现有的类别,我想以干净且可维护的方式在这些子类中添加通用功能。

一种方法是将类别添加到它们的公共超类(NSManagedObject),但是当我想将方法​​添加到三个 NSManagedObject 子类(@ 987654327@, Chapter, Page)。

另一个解决方案是继承NSManagedObject 的子类,然后让BookChapterPage 继承自该NSManagedObject 子类。这是最干净、最直接的方法。这种方法的最大缺点是当数据模型发生变化并且 Xcode 重新生成子类时,它会将它们重置为继承自 NSManagedObject 而不是 SubclassedManagedObject。如果可能的话,我想避免使用类似 mogenerator/Xmo'd 的东西。

是否可以在不重复代码的情况下在多个类上添加单个类别?

谢谢。

【问题讨论】:

  • 我并不是要劫持这个问题,但也许这会增加上下文。我有相同的需求(一个类别,多个类),但需要两个非并行类:具有完整实现的具体模型和具有共享动态实现的模型的 NSProxy。由于我希望两者具有相同的接口,因此我需要在 @interfaces 中使用完全相同的属性声明。模型的实现有自定义的 setter/getter,而代理只有 @dynamic 声明。
  • NM,那太愚蠢了。代理不需要实现,只需要接口。

标签: objective-c ios cocoa-touch cocoa objective-c-category


【解决方案1】:

对于您那里的其他东西,据我所知,您必须返回并为您的三个类创建一个公共子类才能获得您想要的东西。但我可以指出的是,与其在那里做你自己的 isSupported 方法,不如简单地使用 NSObject 的 respondsToSelector 方法来判断你的类是否实现了你希望这三个类使用的任何特殊方法,这应该更好而不是检查所有这些类。如果您添加额外的类会更好,因为您不必维护或扩展庞大的 isMemberOfClass 检查列表

【讨论】:

    【解决方案2】:

    为什么不在一个中心类中创建共享代码类级别的方法,您只需通过每个类别中的 shell 方法调用它?

    如果您的类别正在存储关联的引用,您可以将它们传递到类级别的方法中以进行操作。

    【讨论】:

    • 这是一个好主意,尽管使用具有类级别方法的共享单独类会增加一个抽象级别,将实际逻辑从定义它的位置移开。
    【解决方案3】:

    这听起来有点像你想要一个 ruby​​ 模块之类的东西。我不知道有什么方法可以在objective-c中做这样的事情。您可以制定一个协议并让您的每个类都符合您的协议,但这并不能解决共享方法实现的问题。

    查看this question,它可能会提供更多见解。

    【讨论】:

      【解决方案4】:

      说在 nsmanagedobject 上提供一个类别“具有将类别的方法添加到所有 NSManagedObject 子类的意外后果”,这有点用词不当。当您将类别代码包含在您正在使用它的文件中时,它只是被链接:您没有修改 nsmanagedobject。

      也就是说,如果代码需要了解其对象,您可以创建这些类符合的协议,然后在代码中使用conformsToProtocol 进行测试。这可能是比测试特定类类型更好的通用方法。

      【讨论】:

      • 如果您在 NSManagedObject (@interface NSManagedObject (MyAdditionalGoodies)) 上声明一个类别,那么您正在在您的程序中修改 NSManagedObject。您至少在添加方法,可能会替换一些方法。
      • 编辑:我从我的问题中删除了类检查代码,因为它与实际问题无关。
      • 感谢彼得的纠正。这里解释了似乎真正发生的事情:stackoverflow.com/questions/7026259/…
      【解决方案5】:

      也许为时已晚.. 但也许有一种方法可以做到这一点.. 但是,你说..需要有相同的超类

      类别.h

      @protocol MyProtocol <NSObject>
      - (NSString*)foo;
      @end
      
      @interface NSArray  (category) <MyProtocol> @end
      @interface NSString (category) <MyProtocol> @end
      

      类别.m

      @interface NSObject (category) <MyProtocol> @end
      @implementation NSObject (category)
      - (NSString*)foo
      {
          return @"bar";
      }
      @end
      

      我也不喜欢这个,但它有效

      【讨论】:

        【解决方案6】:

        我仍然不知道在 Objective-C 中执行此操作的干净方法,但在 Swift 2.0 中,这可以通过向现有协议添加函数和/或属性来使用协议扩展来实现。然后,该协议可以被任意数量的类、结构和/或枚举采用。

        protocol Numbered {
            func number() -> Int
        }
        
        extension Numbered {
            func number() -> Int {
                return Int(arc4random()) % 10
            }
        }
        
        class Book : Numbered {
        
        }
        
        class Chapter : Numbered {
        
        }
        
        class Page : Numbered {
        
        }
        
        let myBook = Book()
        let myChapter = Chapter()
        let myPage = Page()
        
        print("myBook.number() = \(myBook.number())")
        print("myChapter.number() = \(myChapter.number())")
        print("myPage.number() = \(myPage.number())")
        

        在所有三个类(BookChapterPage)上正确实现number()

        myBook.number() = 5
        myChapter.number() = 2
        myPage.number() = 8
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-08-10
          • 1970-01-01
          • 2014-06-14
          • 2017-11-01
          • 1970-01-01
          • 2022-10-12
          相关资源
          最近更新 更多