A car dealership needs a program to store information about the cars for sale. For each car, they want to keep track of the following information: number of doors (2 or 4), whether the car has air conditioning, and its average number of miles per gallon. Which of the following is the best design?
(A) Use one class, Car, which has three data fields:
int numDoors, boolean hasAir, and double milesPerGallon.
(B) Use four unrelated classes: Car, Doors, AirConditioning, and MilesPerGallon.
(C) Use a class car which has three subclasses: Doors, AirConditioning, and MilesPerGallon.
(D) Use a class Car, which has a subclass Doors, with a subclass AirConditioning, with a subclass MilesPerGallon.
(E) Use three classes: Doors, AirConditioning, and MilesPerGallon, each with a subclass Car.
OK so they are looking for the BEST design out of the five. I'm guessing best means the one with the least lines that works properly.
Looking at them, D looks like it wouldn't work properly because AirConditioning is a subclass or Doors, and MilesPerGallon a subclass of AirConditioning, and that doesn't make logical sense.
For E, using three classes, each with a subclass Car, doesn't make sense.
For B, using four unrelated classes would be inefficient.
So I think it's between A and C. Since I don't think it's necessary to have subclasses to accomplish the objective, I think A is the best answer. Am I right? *checks answer* Yep! It's A.
Car is a Door?
Car is an AirConditioning?
Car is a MilesPerGallon?
That is the sort of thing you need to ask. Incidently, the first 2 pass the has-a test and is a good canditate for composition, not inheritance. The Strategy or Decorator pattern would be good here, but that might be a bit too much info right now.
From what you said, I see that the is-a question is used to determine if a subclass belongs in a class.
What is the has-a question used to determine?
Dog has a tail. This could be done several ways. A simple boolean hasTail in Dog might suffice, but a Tail object in Dog could be more useful. This way the tail could wag or not, or whatever. This is essentially composition.
Dogs also Bark, but some really yap, howl, ect, so you could have a Barkable interface or abstract class. So a Yap class that implements Barkable. So in Dog, you can have a Barkable reference, to make things more flexible.
But Dog is a Pet also, and you can't have multiple inheritance, but you can inherit any behavior or characteristics of pet by implementing a Pet interface.
So we have a Dog which is a Animal and a Pet and has a Tail and bark determined at runtime. It is not a perfect example, but hopefully will illistrate things well enough.
There is a lot to this subject and goes deeper with design patterns. More then can be fit in a message board post. Hopefully this will make the basic a bit more clear.
[ April 30, 2006: Message edited by: Rusty Shackleford ]
For example, if Orange is a subclass of Fruit, any time someone asks for a Fruit you should be able to give them an Orange and they will be happy. If a police officer needs a motor vehicle for an emergency, I should be able to give him/her my (car, RV, motorcycle) and it should meet their need.
The problem with "is a" as a test is that the business environment in which we often program is too "squishy"...what might sound OK in a sentence would not pass the substitution test. "A Homeowner Policy is a Contract" might sound OK, but might not meet every requirement for Contract as defined in the business.
English is just too damn flexible to be worthwhile for testing object relationships rigorously.
A homeowner policy is a contract, and so is a partnership agreement. That a partnership agreement and a insurance policy are very different doesn't invalidate the fact that both can have contract as a super class. That is the entire point of inheritance and polymorphism. It can be written in such a way that the invoking program doesn't need to care which type of contract is being used, the desired attributes will be there.
A homeowner policy is a contract, and so is a partnership agreement.
You are using terms from an environment without defining them, and without explaining the environment. I will say that in many, if not most, environments the statement is accurate. But it doesn't mean that it works from an object-oriented perspective unless the classes have been defined accordingly.
Let's take the word "transaction". It means different things to different people. In a database, we mean a unit of work which must succeeed or fail as a whole. In a business, we may instead say that a transaction is an event on a particular day that results in an exchange of money between a customer and the business. Is an update to the inventory a transaction? "Yes", you reply, because you are thinking about it from the database perspective. "No", the SME answers, because no money is exhanged.
I repeat: "is a" is a perfectly acceptable shorthand terms that represents generalization. It is not a test. The only acceptable test for inheritance is that of replaceability. If it fails the test of replaceability, it must properly be modeled in some other way than inheritance.
What's really going to be hard is the AP Music Theory exam I take tomorrow...
"English is just too damn flexible to be worthwhile for testing object relationships rigorously."
No it is not, it works just fine for rigorous definitions in mathematics, you just have to be careful. Just because transaction can have multiple meanings doesn't mean is-a isn't rigorous enough. That is why things like packages exist. You can have 2 transaction base classes in 2 packages that do two totally different things, yet both work well. Like mathematics, it is all relative to the context, given due care to the wording. Ever seen a proof that there exists infinite sets of different sizes(cardinality)? By the everday use of the word that seems to be senseless, but yet it is true. In much the same way, with care towards wording and attention to context you can subclass in a logical and flexible manner using is-a.
I do agree with you on one thing: understanding the fundamental principles of OO is critical before going on to more advanced concepts. In my experience, the vast majority of developers don't really understand these principles...they understand the mechanism, but not the rationale.
I'm not skipping any intro courses even if I pass. I know a girl who took 13 AP exams in high school and passed 12 of them with 4s and 5s. She actually only took 5 AP classes in high school, all the other work she did on her own. She went into college as a junior and did well there too. She then went on to law school and is doing well there. She's not me; I'm not motivated to work my butt off like that.
Originally posted by Rusty Shackleford:
It seems to me that it would be best if you don't pass. That might sound harsh, but look at how many times you have misunderstood concepts. Do you really want to jump ahead of an intro class, not having a firm grasp on the basics? Most classes past intro classes, expect you do know the prereqs, and will not slow down for you, which can be frusterating and waste lots of time and money, not too mention kill your GPA. Please don't take it in the wrong way, it is just an opinion of a computer science honors student, that started college with near zero knowlege of programming and hardware design. although admittedly Java is not my strongest area.
It would be nice if I pass, however, because it would please not only my parents but also my teacher. None of my teacher's students have ever passed, and sad but true, I'm the best student in our 18 person class in terms of knowledge and grades. Only one other person besides me even studied (the little bit that we did) and tried to pass the test.