在Objective-C中子类化是不好的做法吗?

时间:2023-01-15 14:54:19

After reading lots of blogs, forum entries and several Apple docs, I still don't know whether extensive subclassing in Objective-C is a wise thing to do or not.

在阅读了大量的博客、论坛条目和几个苹果文档之后,我仍然不知道在Objective-C中进行大量的子类化是否明智。

Take for example the following case:

以下列情况为例:

Say I'm developing a puzzle game which has a lot of elements. All of those elements share a certain amount of the same behaviour. Then, within my collection of elements, different groups of elements share equal behaviour, distinguishing groups from groups, etc...

假设我正在开发一个有很多元素的益智游戏。所有这些元素都有相同的行为。然后,在我的元素集合中,不同的元素组有相同的行为,区分组与组等等……

So, after determining what inherits from what, I decided to subclass out of oblivion. And why shouldn't I? Considering the ease tweaking general behaviour takes with this model, I think I accomplished something OOP is meant for.

所以,在确定什么继承了什么之后,我决定从遗忘中子类化。我为什么不能?考虑到这个模型对一般行为的轻松调整,我认为我完成了OOP的目的。

But, - and this is the source of my question - Apple mentions using delegates, data source methods, and informal protocols in favour of subclassing. It really boggles my mind why?

但是,——这是我的问题的来源——Apple提到了使用委托、数据源方法和支持子类化的非正式协议。我真搞不懂为什么?

There seem to be two camps. Those in favor of subclassing, those in fafor of not. It depends on personal taste apparently. I'm wondering what the pros and cons are of subclassing massively and not subclassing massively?

似乎有两个阵营。赞成子类化的,不赞成的。这显然取决于个人品味。我在想,究竟是什么好处和坏处是大规模的子类化,而不是大规模的子类化?

To wrap it up, my question is simple: Am I right? And why or why not?

最后,我的问题很简单:我是对的吗?为什么或者为什么不呢?

9 个解决方案

#1


10  

Personally, I follow this rule: I can create a subclass if it respects the Liskov substitution principle.

就我个人而言,我遵循这个规则:如果它尊重Liskov替换原则,我可以创建一个子类。

#2


12  

Delegation is a means of using the composition technique to replace some aspects of coding you would otherwise subclass for. As such, it boils down to the age old question of the task at hand needing one large thing that knows how to do a lot, or if you have a loose network of specialized objects (a very UNIX sort of model of responsibility).

委托是一种使用组合技术来替换您本来要子类化的代码的某些方面的方法。因此,它可以归结为一个老问题:手头的任务需要一个知道如何做很多事情的大的东西,或者如果你有一个松散的专门对象网络(一个非常UNIX的责任模型)。

Using a combination of delegates and protocols (to define what the delegates are supposed to be able to do) provides a great deal of flexibility of behavior and ease of coding - going back to that Liskov substitution principle, when you subclass you have to be careful you don't do anything a user of the whole class would find unexpected. But if you are simply making a delegate object then you have much less to be responsible for, only that the delegate methods you implement do what that one protocol calls for, beyond that you don't care.

使用的组合代表和协议(定义代表应该能够做什么)的行为提供了很大的灵活性和易用性的编码——回到Liskov替换原则,当你子类必须小心你不做任何事情整个类的用户会发现意想不到的。但是如果你只是做一个委托对象,那么你要负责的就会少得多,只需要你实现的委托方法做一个协议所要求的事情,除此之外你并不关心。

There are still many good reasons to use subclasses, if you truly have shared behavior and variables between a number of classes it may make a lot of sense to subclass. But if you can take advantage of the delegate concept you'll often make your classes easier to extend or use in ways you the designer may not have expected.

使用子类仍然有很多很好的理由,如果您确实有一些类之间的共享行为和变量,那么子类化可能很有意义。但是,如果您能够利用委托概念,您通常会使您的类更容易扩展或以设计者可能没有预料到的方式使用。

I tend to be more of a fan of formal protocols than informal ones, because not only do formal protocols make sure you have the methods a class treating you as a delegate expect, but also because the protocol definition is a natural place to document what you expect from a delegate that implements those methods.

我往往更喜欢正式的比非正式的协议,因为不仅正式协议确保你有一个类的方法把你作为代表希望,还因为协议定义是一个自然的地方记录你期望从一个委托实现这些方法。

#3


7  

Subclassing has it's benefits, but it also has some drawbacks. As a general rule, I try to avoid implementation inheritance and instead use interface inheritance and delegation.

子类化有它的好处,但它也有一些缺点。一般来说,我尽量避免实现继承,而是使用接口继承和委托。

One of the reasons I do this is because when you inherit implementation, you can wind up with problems if you override methods but don't adhere to their (sometimes undocumented contract). Additionally, I find walking class hierarchies with implementation inheritance difficult because methods can be overridden or implemented at any level. Finally, when subclassing you can only widen an interface, you can't narrow it. This leads to leaky abstractions. A good example of this is java.util.Stack which extends java.util.Vector. I shouldn't be able to treat a stack as a Vector. Doing so only allows the consumer to run around the interface.

我这样做的原因之一是,当您继承实现时,如果您重写方法,但不遵守它们(有时是无文档的契约),您就会遇到问题。另外,我发现使用实现继承困难的行走类层次结构很困难,因为方法可以在任何级别上被重写或实现。最后,当子类化时,你只能拓宽一个接口,你不能缩小它。这导致了抽象的漏洞。一个很好的例子是java.util。堆栈java.util.Vector延伸。我不应该把堆栈当作向量。这样做只允许使用者围绕接口运行。

Others have mentioned the Liskov Substitution Principle. I think that using that would have certainly cleared up the java.util.Stack problem but it can also lead to very deep class hierarchies in order to put ensure that classes get only the methods they are supposed to have.

其他人提到了李斯科夫换元原理。我认为使用它肯定可以清除java.util。堆栈问题,但它也可能导致非常深入的类层次结构,以确保类只获得它们应该具有的方法。

Instead, with interface inheritance there is essentially no class hierarchy because interfaces rarely need to extend one another. The classes simply implement the interfaces that they need to and can therefore be treated in the correct way by the consumer. Additionally, because there is no implementation inheritance, consumers of these classes won't infer their behavior due to previous experience with a parent class.

相反,对于接口继承,基本上不存在类层次结构,因为接口很少需要相互扩展。类只是实现了它们需要的接口,因此使用者可以以正确的方式对待它们。此外,由于没有实现继承,这些类的使用者不会因为以前使用父类的经验而推断他们的行为。

In the end though, it doesn't really matter which way you go. Both are perfectly acceptable. It's really more a matter of what you're more comfortable with and what the frameworks that you're working with encourage. As the old saying goes: "When in Rome do as Romans do."

最后,你走哪条路并不重要。都是完全可以接受的。更重要的是你更愿意接受什么样的框架,以及你在鼓励哪些框架。俗话说:“入乡随俗。”

#4


6  

There's nothing wrong with using inheritance in Objective-C. Apple uses it quite a bit. For instance, in Cocoa-touch, the inheritance tree of UIButton is UIControl : UIView : UIResponder : NSObject.

在Objective-C中使用继承没有什么问题。苹果用了很多。例如,在Cocoa-touch中,UIButton的继承树是UIControl: UIView: UIResponder: NSObject。

I think Martin hit on an important point in mentioning the Liskov substitution principle. Also, proper use of inheritance requires that the implementer of the subclass has a deep knowledge of the super class. If you've ever struggled to extend a non-trivial class in a complex framework, you know that there's always a learning curve. In addition, implementation details of the super class often "leak through" to the subclass, which is a big pain in the @$& for framework builders.

我认为马丁在提到Liskov替换原则时提到了一个重点。另外,正确使用继承需要子类的实现者对超类有深入的了解。如果您曾经在一个复杂的框架中努力扩展一个非平凡类,那么您就知道总是有一个学习曲线。此外,超类的实现细节经常“泄漏”到子类,这是@$&框架构建器的一大痛苦。

Apple chose to use delegation in many instances to address these problems; non-trivial classes like UIApplication expose common extension points through a delegate object so most developers have both an easier learning curve and a more loosely coupled way to add application specific behavior -- extending UIApplication directly is rarely necessary.

苹果选择在许多情况下使用授权来解决这些问题;像UIApplication这样的非平凡类通过委托对象公开公共扩展点,所以大多数开发人员都有更简单的学习曲线和更松耦合的方式来添加应用程序特定的行为——直接扩展UIApplication几乎没有必要。

In your case, for your application specific code, use which ever techniques you're comfortable with and work best for your design. Inheritance is a great tool when used appropriately.

在您的例子中,对于您的应用程序特定的代码,请使用您最熟悉的技术,并使其最适合您的设计。如果使用得当,继承是一个很好的工具。

I frequently see application programmers draw lessons from framework designs and trying to apply them to their application code (this is common in Java, C++ and Python worlds as well as Objective-C). While it's good to think about and understand the choices framework designers made, those lessons don't always apply to application code.

我经常看到应用程序程序员从框架设计中吸取经验教训,并试图将它们应用到应用程序代码中(这在Java、c++和Python以及Objective-C中都很常见)。虽然思考和理解框架设计者所做的选择是很好的,但是这些经验并不总是适用于应用程序代码。

#5


4  

In general you should avoid subclassing API classes if there exist delegates, etc that accomplish what you want to do. In your own code subclassing is often nicer, but it really does depend on your goals, eg. if you're providing an API you should provide a delegate based API rather than assuming subclassing.

一般来说,如果存在委托,您应该避免子类化API类。在您自己的代码中,子类化通常更好一些,但是它确实取决于您的目标(例如)。如果您正在提供一个API,您应该提供一个基于委托的API,而不是假设子类化。

When dealing with APIs subclassing has more potential bugs -- eg. if any class in the class hierarchy gets a new method that has the same name as your addition you make break stuff. And also, if you're providing a useful/helper type function there's a chance that in the future something similar will be added to the actual class you were subclassing, and that might be more efficient, etc but your override will hide it.

当处理api时,子类化有更多的潜在bug——例如。如果类层次结构中的任何类都有一个新方法,它的名称与您的添加相同,那么您就可以创建break的内容。而且,如果你提供了一个有用的/helper类型函数,将来有可能类似的东西会被添加到你要子类化的实际类中,这可能会更有效,等等,但是你的覆盖会隐藏它。

#6


4  

Please read the Apple documentation "Adding behavior to a Cocoa program"!. Under "Inheriting from a Cocoa class" section, see the 2nd paragraph. Apple clearly mentions that Subclassing is the primary way of adding application specific behavior to the framework (please note, FRAMEWORK).
MVC pattern does not completely disallow the use of subclasses or subtypes. Atleast I have not seen this recommendation from either Apple or others (if I have missed please feel free to point me to the right source of information about this). If you are subclassing api classes only within your application, please go ahead, no one's stopping you but do take care that it does not break the behavior of the class/api as a whole. Subclassing is great way of extending the framework api's functionality. We see a lot of subclassing within the Apple IOS framework APIs too. As a developer one has to take care the implementation is well documented and not duplicated accidentally by another developer. Its another ball game altogether if your application is a set of API classes that you plan to distribute as reusable component.

请阅读苹果文档“添加行为到一个Cocoa程序”!在“继承可可类”一节中,请参见第二段。Apple明确地提到子类化是向框架添加应用程序特定行为的主要方式(请注意,框架)。MVC模式并不完全不允许使用子类或子类型。至少我还没见过苹果或其他公司的推荐信(如果我错过了,请随时给我指出正确的信息来源)。如果您只是在应用程序中子类化api类,请继续,没有人会阻止您,但是请注意不要破坏类/api的整体行为。子类化是扩展框架api功能的好方法。我们在苹果IOS框架api中也看到了很多子类化。作为一个开发人员,您必须注意实现的文档是完整的,并且不会被其他开发人员意外地复制。如果您的应用程序是一组您计划将其作为可重用组件分发的API类,那么它将是另一种球类游戏。

IMHO, rather than asking around what the best practice is, first read the related documentation thoroughly, implement and test it. Make your own judgement. You know best about what you're up to. It's easy for others (like me and so many others) to just read stuff from different sources on the Net and throw around terms. Be your own judge, it has worked for me so far.

IMHO,而不是询问最佳实践是什么,首先要彻底阅读相关文档,实现并测试它。作出自己的判断。你最了解自己在做什么。对于其他人(像我和其他很多人)来说,在网上阅读不同来源的文章并抛出术语是很容易的。做你自己的判断,到目前为止,它对我起了作用。

#7


3  

I really think it depends on what you're trying to do. If the puzzle game you describe in the example really does have a set of unique elements that share common attributes, and there's no provided classes - say, for example, "NSPuzzlePiece" - that fit your needs, then I don't see a problem with subclassing extensively.

我真的认为这取决于你想做什么。如果您在示例中描述的难题游戏确实有一组共享公共属性的独特元素,并且没有提供的类(例如,“nspulepiece”)——能够满足您的需要,那么我不认为子类化有什么问题。

In my experience, delegates, data source methods, and informal protocols are much more useful when Apple has provided a class that already does something close to what you want it to do.

在我的经验中,委托、数据源方法和非正式协议更有用,因为苹果提供了一个类,它已经完成了您希望它做的事情。

For example, say you're building an app that uses a table. There is (and I speak here of the iPhone SDK, since that's where I have experience) a class UITableView that does all the little niceties of creating a table for interaction with the user, and it's much more efficient to define a data source for an instance of UITableView than it is to completely subclass UITableView and redefine or extend its methods to customize its behavior.

例如,假设您正在构建一个使用表的应用程序。有(iPhone SDK的和我说,因为我有经验)一个类UITableView,创建一个表的所有小细节与用户的交互,这是更有效定义数据源的一个实例UITableView比完全UITableView子类重新定义或扩展其方法自定义其行为。

Similar concepts go for delegates and protocols. If you can fit your ideas into Apple's classes, then it's usually easier (and will work more smoothly) to do so and use data source, delegates, and protocols than it is to create your own subclasses. It helps you avoid extra work and wasting time, and is usually less error-prone. Apple's classes have taken care of the business of making functions efficient and debugging; the more you can work with them, the fewer mistakes your program will have in the long run.

类似的概念也适用于委托和协议。如果你能将你的想法融入到苹果的类中,那么比起创建你自己的子类,使用数据源、委托和协议通常更容易(而且工作起来也更顺利)。它可以帮助你避免额外的工作和浪费时间,而且通常也不容易出错。苹果的课程专注于使功能高效和调试;您使用它们的次数越多,从长远来看,您的程序所犯的错误就越少。

#8


2  

my impression of ADC's emphasis 'against' subclassing has more to do with the legacy of how the operating system has evolved... back in the day (Mac Classic aka os9) when c++ was the primary interface to most of the mac toolbox, subclassing was the de-facto standard in order for a programmer to modify the behaviour of commonplace OS features (and this was indeed sometimes a pain in the neck and meant that one had to be very careful that any and all modifications behaved predictably and didn't break any standard behaviour).

我对ADC强调“反对”子类化的印象更多地与操作系统是如何进化的遗产有关……过去(Mac经典又名os9)当c++的主要接口的Mac工具箱,子类化的实际标准是为了使程序员修改常见操作系统的行为特征(这确实是有时令人讨厌,意味着一个不得不非常小心,任何和所有的修改行为可以预见,没有打破任何标准的行为)。

this being said, MY IMPRESSION of ADC's emphasis against subclassing is not putting forth a case for designing an application's class hierarchy without inheritance, BUT INSTEAD to point out that in the new way of doing things (ie OSX) there are in most cases more appropriate means to go about customizing standard behavior without needing to subclass.

这就是说,我对ADC的印象对子类化的重点不是提出一个案例设计应用程序的类层次结构没有继承,而是指出,在新的做事的方式(即OSX)有在大多数情况下更合适的方式去定制标准的行为,而不需要子类。

So, by all means, design your puzzle program's architecture as robustly as you can, leveraging inheritance as you see fit!

因此,无论如何,尽可能健壮地设计您的难题程序的体系结构,利用您认为合适的继承!

looking forward to seeing your cool new puzzle application!

期待看到您的酷新拼图应用!

|K<

| K <

#9


0  

Apple indeed appears to passively discourage subclassing with Objective-C.

苹果似乎确实在被动地反对使用Objective-C进行细分。

It is an axiom of OOP design to Favor composition over implementation.

OOP设计的一个原则是喜欢组合而不是实现。

#1


10  

Personally, I follow this rule: I can create a subclass if it respects the Liskov substitution principle.

就我个人而言,我遵循这个规则:如果它尊重Liskov替换原则,我可以创建一个子类。

#2


12  

Delegation is a means of using the composition technique to replace some aspects of coding you would otherwise subclass for. As such, it boils down to the age old question of the task at hand needing one large thing that knows how to do a lot, or if you have a loose network of specialized objects (a very UNIX sort of model of responsibility).

委托是一种使用组合技术来替换您本来要子类化的代码的某些方面的方法。因此,它可以归结为一个老问题:手头的任务需要一个知道如何做很多事情的大的东西,或者如果你有一个松散的专门对象网络(一个非常UNIX的责任模型)。

Using a combination of delegates and protocols (to define what the delegates are supposed to be able to do) provides a great deal of flexibility of behavior and ease of coding - going back to that Liskov substitution principle, when you subclass you have to be careful you don't do anything a user of the whole class would find unexpected. But if you are simply making a delegate object then you have much less to be responsible for, only that the delegate methods you implement do what that one protocol calls for, beyond that you don't care.

使用的组合代表和协议(定义代表应该能够做什么)的行为提供了很大的灵活性和易用性的编码——回到Liskov替换原则,当你子类必须小心你不做任何事情整个类的用户会发现意想不到的。但是如果你只是做一个委托对象,那么你要负责的就会少得多,只需要你实现的委托方法做一个协议所要求的事情,除此之外你并不关心。

There are still many good reasons to use subclasses, if you truly have shared behavior and variables between a number of classes it may make a lot of sense to subclass. But if you can take advantage of the delegate concept you'll often make your classes easier to extend or use in ways you the designer may not have expected.

使用子类仍然有很多很好的理由,如果您确实有一些类之间的共享行为和变量,那么子类化可能很有意义。但是,如果您能够利用委托概念,您通常会使您的类更容易扩展或以设计者可能没有预料到的方式使用。

I tend to be more of a fan of formal protocols than informal ones, because not only do formal protocols make sure you have the methods a class treating you as a delegate expect, but also because the protocol definition is a natural place to document what you expect from a delegate that implements those methods.

我往往更喜欢正式的比非正式的协议,因为不仅正式协议确保你有一个类的方法把你作为代表希望,还因为协议定义是一个自然的地方记录你期望从一个委托实现这些方法。

#3


7  

Subclassing has it's benefits, but it also has some drawbacks. As a general rule, I try to avoid implementation inheritance and instead use interface inheritance and delegation.

子类化有它的好处,但它也有一些缺点。一般来说,我尽量避免实现继承,而是使用接口继承和委托。

One of the reasons I do this is because when you inherit implementation, you can wind up with problems if you override methods but don't adhere to their (sometimes undocumented contract). Additionally, I find walking class hierarchies with implementation inheritance difficult because methods can be overridden or implemented at any level. Finally, when subclassing you can only widen an interface, you can't narrow it. This leads to leaky abstractions. A good example of this is java.util.Stack which extends java.util.Vector. I shouldn't be able to treat a stack as a Vector. Doing so only allows the consumer to run around the interface.

我这样做的原因之一是,当您继承实现时,如果您重写方法,但不遵守它们(有时是无文档的契约),您就会遇到问题。另外,我发现使用实现继承困难的行走类层次结构很困难,因为方法可以在任何级别上被重写或实现。最后,当子类化时,你只能拓宽一个接口,你不能缩小它。这导致了抽象的漏洞。一个很好的例子是java.util。堆栈java.util.Vector延伸。我不应该把堆栈当作向量。这样做只允许使用者围绕接口运行。

Others have mentioned the Liskov Substitution Principle. I think that using that would have certainly cleared up the java.util.Stack problem but it can also lead to very deep class hierarchies in order to put ensure that classes get only the methods they are supposed to have.

其他人提到了李斯科夫换元原理。我认为使用它肯定可以清除java.util。堆栈问题,但它也可能导致非常深入的类层次结构,以确保类只获得它们应该具有的方法。

Instead, with interface inheritance there is essentially no class hierarchy because interfaces rarely need to extend one another. The classes simply implement the interfaces that they need to and can therefore be treated in the correct way by the consumer. Additionally, because there is no implementation inheritance, consumers of these classes won't infer their behavior due to previous experience with a parent class.

相反,对于接口继承,基本上不存在类层次结构,因为接口很少需要相互扩展。类只是实现了它们需要的接口,因此使用者可以以正确的方式对待它们。此外,由于没有实现继承,这些类的使用者不会因为以前使用父类的经验而推断他们的行为。

In the end though, it doesn't really matter which way you go. Both are perfectly acceptable. It's really more a matter of what you're more comfortable with and what the frameworks that you're working with encourage. As the old saying goes: "When in Rome do as Romans do."

最后,你走哪条路并不重要。都是完全可以接受的。更重要的是你更愿意接受什么样的框架,以及你在鼓励哪些框架。俗话说:“入乡随俗。”

#4


6  

There's nothing wrong with using inheritance in Objective-C. Apple uses it quite a bit. For instance, in Cocoa-touch, the inheritance tree of UIButton is UIControl : UIView : UIResponder : NSObject.

在Objective-C中使用继承没有什么问题。苹果用了很多。例如,在Cocoa-touch中,UIButton的继承树是UIControl: UIView: UIResponder: NSObject。

I think Martin hit on an important point in mentioning the Liskov substitution principle. Also, proper use of inheritance requires that the implementer of the subclass has a deep knowledge of the super class. If you've ever struggled to extend a non-trivial class in a complex framework, you know that there's always a learning curve. In addition, implementation details of the super class often "leak through" to the subclass, which is a big pain in the @$& for framework builders.

我认为马丁在提到Liskov替换原则时提到了一个重点。另外,正确使用继承需要子类的实现者对超类有深入的了解。如果您曾经在一个复杂的框架中努力扩展一个非平凡类,那么您就知道总是有一个学习曲线。此外,超类的实现细节经常“泄漏”到子类,这是@$&框架构建器的一大痛苦。

Apple chose to use delegation in many instances to address these problems; non-trivial classes like UIApplication expose common extension points through a delegate object so most developers have both an easier learning curve and a more loosely coupled way to add application specific behavior -- extending UIApplication directly is rarely necessary.

苹果选择在许多情况下使用授权来解决这些问题;像UIApplication这样的非平凡类通过委托对象公开公共扩展点,所以大多数开发人员都有更简单的学习曲线和更松耦合的方式来添加应用程序特定的行为——直接扩展UIApplication几乎没有必要。

In your case, for your application specific code, use which ever techniques you're comfortable with and work best for your design. Inheritance is a great tool when used appropriately.

在您的例子中,对于您的应用程序特定的代码,请使用您最熟悉的技术,并使其最适合您的设计。如果使用得当,继承是一个很好的工具。

I frequently see application programmers draw lessons from framework designs and trying to apply them to their application code (this is common in Java, C++ and Python worlds as well as Objective-C). While it's good to think about and understand the choices framework designers made, those lessons don't always apply to application code.

我经常看到应用程序程序员从框架设计中吸取经验教训,并试图将它们应用到应用程序代码中(这在Java、c++和Python以及Objective-C中都很常见)。虽然思考和理解框架设计者所做的选择是很好的,但是这些经验并不总是适用于应用程序代码。

#5


4  

In general you should avoid subclassing API classes if there exist delegates, etc that accomplish what you want to do. In your own code subclassing is often nicer, but it really does depend on your goals, eg. if you're providing an API you should provide a delegate based API rather than assuming subclassing.

一般来说,如果存在委托,您应该避免子类化API类。在您自己的代码中,子类化通常更好一些,但是它确实取决于您的目标(例如)。如果您正在提供一个API,您应该提供一个基于委托的API,而不是假设子类化。

When dealing with APIs subclassing has more potential bugs -- eg. if any class in the class hierarchy gets a new method that has the same name as your addition you make break stuff. And also, if you're providing a useful/helper type function there's a chance that in the future something similar will be added to the actual class you were subclassing, and that might be more efficient, etc but your override will hide it.

当处理api时,子类化有更多的潜在bug——例如。如果类层次结构中的任何类都有一个新方法,它的名称与您的添加相同,那么您就可以创建break的内容。而且,如果你提供了一个有用的/helper类型函数,将来有可能类似的东西会被添加到你要子类化的实际类中,这可能会更有效,等等,但是你的覆盖会隐藏它。

#6


4  

Please read the Apple documentation "Adding behavior to a Cocoa program"!. Under "Inheriting from a Cocoa class" section, see the 2nd paragraph. Apple clearly mentions that Subclassing is the primary way of adding application specific behavior to the framework (please note, FRAMEWORK).
MVC pattern does not completely disallow the use of subclasses or subtypes. Atleast I have not seen this recommendation from either Apple or others (if I have missed please feel free to point me to the right source of information about this). If you are subclassing api classes only within your application, please go ahead, no one's stopping you but do take care that it does not break the behavior of the class/api as a whole. Subclassing is great way of extending the framework api's functionality. We see a lot of subclassing within the Apple IOS framework APIs too. As a developer one has to take care the implementation is well documented and not duplicated accidentally by another developer. Its another ball game altogether if your application is a set of API classes that you plan to distribute as reusable component.

请阅读苹果文档“添加行为到一个Cocoa程序”!在“继承可可类”一节中,请参见第二段。Apple明确地提到子类化是向框架添加应用程序特定行为的主要方式(请注意,框架)。MVC模式并不完全不允许使用子类或子类型。至少我还没见过苹果或其他公司的推荐信(如果我错过了,请随时给我指出正确的信息来源)。如果您只是在应用程序中子类化api类,请继续,没有人会阻止您,但是请注意不要破坏类/api的整体行为。子类化是扩展框架api功能的好方法。我们在苹果IOS框架api中也看到了很多子类化。作为一个开发人员,您必须注意实现的文档是完整的,并且不会被其他开发人员意外地复制。如果您的应用程序是一组您计划将其作为可重用组件分发的API类,那么它将是另一种球类游戏。

IMHO, rather than asking around what the best practice is, first read the related documentation thoroughly, implement and test it. Make your own judgement. You know best about what you're up to. It's easy for others (like me and so many others) to just read stuff from different sources on the Net and throw around terms. Be your own judge, it has worked for me so far.

IMHO,而不是询问最佳实践是什么,首先要彻底阅读相关文档,实现并测试它。作出自己的判断。你最了解自己在做什么。对于其他人(像我和其他很多人)来说,在网上阅读不同来源的文章并抛出术语是很容易的。做你自己的判断,到目前为止,它对我起了作用。

#7


3  

I really think it depends on what you're trying to do. If the puzzle game you describe in the example really does have a set of unique elements that share common attributes, and there's no provided classes - say, for example, "NSPuzzlePiece" - that fit your needs, then I don't see a problem with subclassing extensively.

我真的认为这取决于你想做什么。如果您在示例中描述的难题游戏确实有一组共享公共属性的独特元素,并且没有提供的类(例如,“nspulepiece”)——能够满足您的需要,那么我不认为子类化有什么问题。

In my experience, delegates, data source methods, and informal protocols are much more useful when Apple has provided a class that already does something close to what you want it to do.

在我的经验中,委托、数据源方法和非正式协议更有用,因为苹果提供了一个类,它已经完成了您希望它做的事情。

For example, say you're building an app that uses a table. There is (and I speak here of the iPhone SDK, since that's where I have experience) a class UITableView that does all the little niceties of creating a table for interaction with the user, and it's much more efficient to define a data source for an instance of UITableView than it is to completely subclass UITableView and redefine or extend its methods to customize its behavior.

例如,假设您正在构建一个使用表的应用程序。有(iPhone SDK的和我说,因为我有经验)一个类UITableView,创建一个表的所有小细节与用户的交互,这是更有效定义数据源的一个实例UITableView比完全UITableView子类重新定义或扩展其方法自定义其行为。

Similar concepts go for delegates and protocols. If you can fit your ideas into Apple's classes, then it's usually easier (and will work more smoothly) to do so and use data source, delegates, and protocols than it is to create your own subclasses. It helps you avoid extra work and wasting time, and is usually less error-prone. Apple's classes have taken care of the business of making functions efficient and debugging; the more you can work with them, the fewer mistakes your program will have in the long run.

类似的概念也适用于委托和协议。如果你能将你的想法融入到苹果的类中,那么比起创建你自己的子类,使用数据源、委托和协议通常更容易(而且工作起来也更顺利)。它可以帮助你避免额外的工作和浪费时间,而且通常也不容易出错。苹果的课程专注于使功能高效和调试;您使用它们的次数越多,从长远来看,您的程序所犯的错误就越少。

#8


2  

my impression of ADC's emphasis 'against' subclassing has more to do with the legacy of how the operating system has evolved... back in the day (Mac Classic aka os9) when c++ was the primary interface to most of the mac toolbox, subclassing was the de-facto standard in order for a programmer to modify the behaviour of commonplace OS features (and this was indeed sometimes a pain in the neck and meant that one had to be very careful that any and all modifications behaved predictably and didn't break any standard behaviour).

我对ADC强调“反对”子类化的印象更多地与操作系统是如何进化的遗产有关……过去(Mac经典又名os9)当c++的主要接口的Mac工具箱,子类化的实际标准是为了使程序员修改常见操作系统的行为特征(这确实是有时令人讨厌,意味着一个不得不非常小心,任何和所有的修改行为可以预见,没有打破任何标准的行为)。

this being said, MY IMPRESSION of ADC's emphasis against subclassing is not putting forth a case for designing an application's class hierarchy without inheritance, BUT INSTEAD to point out that in the new way of doing things (ie OSX) there are in most cases more appropriate means to go about customizing standard behavior without needing to subclass.

这就是说,我对ADC的印象对子类化的重点不是提出一个案例设计应用程序的类层次结构没有继承,而是指出,在新的做事的方式(即OSX)有在大多数情况下更合适的方式去定制标准的行为,而不需要子类。

So, by all means, design your puzzle program's architecture as robustly as you can, leveraging inheritance as you see fit!

因此,无论如何,尽可能健壮地设计您的难题程序的体系结构,利用您认为合适的继承!

looking forward to seeing your cool new puzzle application!

期待看到您的酷新拼图应用!

|K<

| K <

#9


0  

Apple indeed appears to passively discourage subclassing with Objective-C.

苹果似乎确实在被动地反对使用Objective-C进行细分。

It is an axiom of OOP design to Favor composition over implementation.

OOP设计的一个原则是喜欢组合而不是实现。