Related
Recently I was talking to a very experienced programmer (8+ years of experience) and he told me that "combining data with functions that work with them in a capsula" is a wrong term for encapsulation. He told me that that was what encapsulation allowed me to do, but not what encapsulation itself was. He told me that as soon as inheritance is not possible without encapsulation, encapsulation must be just a capsula creation (class or anything like that). But today I got interviewed by a less experienced programmer and he was so sure all those classic definitions on wikipedia were right he told me not to even think of passing the interview. So I tried to google all that stuff about encapsulation, and about inheritence not being possible without encapsulation, but didn't find anything. But I can't believe that experienced programmer was wrong, he convienced not only me, but other experienced programmers too. Maybe that correct definition is just something that is lost in the chunks of useless and unimportant info?
So please, give me answers on these two questions:
1) can inheritence be possible without encapsulation? (A class's Inheritence from a class)
2) If not, then can we consider declaring a class encapsulation? Because only after declaring a class we can inherit.
Well, I'm Sorry, but I fail to see the connection between encapsulation and inheritance.
Encapsulation is hiding your internal implementation behind a publicly visible API.
Basically, it's a separation between a type's actual implementation and what it exposes.
In a broad sense, one can look at even the human body and see encapsulation:
For example: You are breathing air in and out, that's your public API, but the internals of what your body is doing with this air are hidden away inside your respiratory system - your lunges passes oxygen to your blood and collects from it carbon dioxide in return - thus changing the mixture ratio of the gasses in the air you breath, but none of this is visible to the outside world.
Inheritance, in the OOP world, is the ability to take a specific object, and derive an even more specific object from it, while adding capabilities (and sometimes mutating existing capabilities via overriding).
For example: A Dog is a kind of Mammal which is a kind of Animal.
An Animal might contain methods such as Eat() and properties such as Weight and Age.
A Mammal might override the Eat() method to implement suckling (from it's mother's breast) as an infant, but depending on it's age eating solid foods.
A Dog might introduce another capability such as Bark.
All of this have nothing to do with encapsulation as desribed in the previous paragraph.
Inheritance is tightly related to another core principle of object oriented programming called Polymorphism - basically, the ability to reference a derived class using it's base class type - perhaps you (or the interviewer) are confusing the two?
However, today is the first time I've seen another definition of encapsulation (and I've been working with oop languages for about two decades now):
A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data.
Under that
definition, encapsulation is the process of creating capsules - stand-alone code snippets that holds data and ways to interact with it - a.k.a types, classes, etc', and is somewhat related to inheritance - in order to inherit a type, that type first needs to be defined.
However, the way I see it, this definition is not enough to define encapsulation. It can be a part of the definition, but not a stand-alone definition of encapsulation.
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.
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.
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?
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?
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).
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.
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.
Personally, I follow this rule: I can create a subclass if it respects the Liskov substitution principle.
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.
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.
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."
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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).
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.
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<
Apple indeed appears to passively discourage subclassing with Objective-C.
It is an axiom of OOP design to Favor composition over implementation.
I am interested in improving my designing capability (designing of classes with its properties, methods etc) for a given.
i.e. How to decide what should be the classes, methods and properties?
Can you guys suggest me good material for improving on this?
Please see:
Any source of good object-oriented design practises?
Best Resources to learn OO Design and Analysis
among many....
Encapsulation: The wrapping up of data and functions into a single unit is known as encapsulation. Or, simply put: putting the data and methods together in a single unit may be a class.
Inheritance: Aquiring the properties from parent class to child class. Or: getting the properties from super class to sub class is known as inheritance.
Polymorphism: The ability to take more that one form, it supports method overloading and method overriding.
Method overloading: When a method in a class having the same method name with different arguments (diff parameters or signatures) is said to be method overloading. This is compile-time polymorphism – using one identifier to refer to multiple items in the same scope.
This is perhaps a question which every programmer thinks of one day.
The designing capability comes with your experience gradually. What I would say is in general scenario if you can visualize the Database objects for a given problem, the rest is a cakewalk (isnt true sometimes if you work on a techie project with no DB)
You can start thinking of objects which are interacting in the real world to complete the process and then map them to classes with appropriate properties and then methods for defining their behavior. Ten you can focus on the classes which contribute to running the workflow and not to any individual real world object.
This gets a lot simplified if we focus on designing the DB before we jump directly to code design.
A lot depends on the pattern you choose - If you see a problem from MVC perspective, you will naturally be drawn towards identifying "controller" classe first and so on.
I guess I need not repeat the golden sources of design and OOPS wisdom - they already posted here or there.
I would recommend you to read up on some UML and design patterns. That gets you going with the thinking in "drawing" terms. You can also get a good grasp of a big class/object a lot easier.
One particular book that is good in this area.
Applying UML and Patterns
Give a look a Domain-Driven Design, which defines entities, value objects, factories, services and repositories and the GRASP patterns (General Responsibility Assignment Software Patterns) e.g. Expert, Creator, Controller.
Have a look at the part 1 screencast the first part is not silverlight but just a command line calculator that starts out as a single bit of code, and is then broken down into classes.
As you may have guessed from the question - I am right at the beginning of the Obj-C journey.
I'm hoping that someone out there knows of some diagrams that depict the relationship between classes, objects and methods - and that they're willing to share.
The problem I'm having is that just looking at code in a textbook doesn't completely explain it - for me at least.
Thanks for reading!
Regards,
Spencer.
No diagrams, but this is the tutorial I wish I'd read before I started:
http://www.cocoadevcentral.com/d/learn_objectivec/
Simple English, all the basic concepts.
Classes are just like classes in any language. They are descriptions.
Objects are like nouns. They are an instance of a class. That is, if you had a description of a generic book (the class) and you made a thesaurus based on that description, the thesaurus would be the object.
Methods are more or less functions. If the objects are nouns, then the messages are verbs.
[ScienceBook getTableOfContents]; //this would like return a table of contents.
Here, the object ScienceBook is being sent a getTableOfContents message (method). So now, the science book would theoretically find, format and return the table of contents to whom ever sent the message.
To some extent, diagrams may not be that helpful to answer the questions you present.
It may help to think of things like this:
A "class" provides the prototype or definition for some thing. For example, a "Person" or a "Car". A common synonym for "class" is "type".
An "object" is a concrete example or instance of a class. For example, you are an instance of "Person", and your car is an instance of "Car".
A "method" is a behavior, action or property of a class. However, a method is normally only meaningful in the context of an object. "Person" -> "Eat" is not meaningful, but "you" -> "Eat" is.
These are fundamental Object-Oriented concepts that are not specific to Objective-C. If you are interested in a general overview that is language-agnostic, I recommend "Object Thinking" by David West. Even though it's from Microsoft Press, it covers the concepts rather than any specific language.
I come from a fairly strong C++ background, but I can definitely remember when I started, I had a hard time grasping at the concept until I found a way to associate it with physical objects.
The word class and object you can use almost interchangeably. Think of an object as a container, like a bucket. The word bucket would be your "class". It is the name you give to the type of object you have.
A bucket has a certain purpose...to carry something. It might be water...or perhaps sand. So perhaps you want to fill the bucket. This would be something you do to the bucket, so in objective-c, this would be your method. You might write something like:
- (void) fillWith:(elementType)something;
So in this case, "something" might be something that represents and object you wish to fill your bucket with.
Your class might look like the following:
typedef enum items {
CRAYONS,
MARKERS,
SAND,
WATER } elementType;
#class Bucket {
elementType item;
}
- (void) fillWith:(elementType)something;
#end
Here's one link to some objective-c samples. Also try the apple development center.
If you're after information on Object Orientated Programming (ie the meaning of classes, objects, methods etc) then I'd advise against Objective-C. Objective-C on the Mac relies heavily on the Cocoa framework. The Cocoa framework is vast and performs a lot of 'magic' which will make it harder to understand the fundamentals of OOP.
An easier place to start would be a language used for web development. It's easier to get to the nuts and bolts of OOP with these languages.
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.
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.
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?
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?
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).
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.
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.
Personally, I follow this rule: I can create a subclass if it respects the Liskov substitution principle.
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.
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.
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."
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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).
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.
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<
Apple indeed appears to passively discourage subclassing with Objective-C.
It is an axiom of OOP design to Favor composition over implementation.