可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Possible Duplicate:
When to use an interface instead of an abstract class and vice versa?
Hi, I am teaching OOP concepts to non-programmers. I wanted to know how can you explain the difference between an interface and an abstract class.
What I am actually looking for, is a real world example that can help highlight the difference between the two.
回答1:
The player Interface
In my Java courses I often use this kind of image and ask: "What is this ?"
Every time someone will say "that's a player". From this image you can teach anybody what an interface is. This Interface allow any user to "play" something. Everybody knows what these buttons mean, even if you don't know what exactly will be done, you can use anything with this interface and you know that the little arrow will "play" and other arrows will probably send you forward or backward.
Everything that will have those buttons will provide a standard behavior that any user will know before even starting to use them.
I usually try to avoid the "contract" word which can be misunderstood.
The DVD player Abstract class
And then from the Play Interface, I go to the VCR (or DVD) player. Every constructor of DVD player must add some special functions to transform a simple unknown player into a DVD player. For example the eject button. And they must correctly implement Player.
The play button will launch the content of the DVD.
But even if DVD Player provide the basic behavior of a DVD player, not everything is done. You can't simply have "a" DVD player, it has a brand and most of the time it has its own firmware. A this time you'll need to extend the DVD Player abstract class to add your own little components.
回答2:
Here's a good comparison of the two: interface vs abstract class. I've copied a specific example from there below:
Interface
Interfaces are often used to describe the peripheral abilities of a class, not its central identity, e.g. An Automobile class might implement the Recyclable interface, which could apply to many otherwise totally unrelated objects.
Abstract class
An abstract class defines the core identity of its descendants. If you defined a Dog abstract class then Dalmatian descendants are Dogs, they are not merely dogable. Implemented interfaces enumerate the general things a class can do, not the things a class is.
回答3:
Interface
An interface is simply a specification. It describes what something MUST do. Nothing more, nothing less. On its own, it is meaningless. It is only useful when someone takes that specification and implements it.
Think of a USB memory stick. It conforms to the specifications of USB. A device communicating with it doesn't need to know or care how the memory stick is going about its job, all it needs to know is that when we ask for data to be written, it is written; conversely, when we ask to read data from it we expect to receive the data.
In computing terms, we use an interface in the same way. If we have:
public interface IUSB
{
Data Read();
bool Write(Data data);
}
We know that anything implementing this interface has to provide an implementation for Read and Write. How or what it does behind the scenes is of no concern to us. By passing an interface around our code we're not tying ourselves down to specific implementations.
Abstract Class
An Abstract Class simply provides us with a means to put in place specification in a base class that derived types must implement, as well as common code that can be used by all derived types.
I've been trying to thing of a good real-world example and have struggled, so can only really come up with a code example.
Say you wanted to implement an employee hierarchy in your code. So you may have:
public abstract class Employee
{
public string FirstName { get; protected set; }
public string LastName { get; protected set; }
public string Grade { get; protected set; }
public int Salary { get; protected set; }
public abstract void GivePayRise();
}
Every employee has a name and an associated job grade. We can model this in the base class with the first 3 properties. However, giving a bonus may not be a straightforward affair, depending on grade etc. So, we mark this as abstract. Every derived type of Employee (Part-Time, Full-Time, Contract, Consultant) has to implement this.
An implementation may be:
public class FullTimeEmployee : Employee
{
public void GivePayRise()
{
Salary *= 1.1;
}
}
public class PartTimeEmployee : Employee
{
public void GivePayRise()
{
Salary *= 1;
}
}
So we want to give a 10% raise to full-time employees, but nothing to part-time ones.
Difficult to give good examples - I generally tend to use interfaces, can't really remember in the past year or so when I've used an abstract class. This could start the whole Abstract Class vs Interface debate, but that's a whole new page.......
回答4:
For everything computer related, I use a cooking dinner example. I start by saying that hard drives are cabinets/storage closets. Memory is like your counter. Processor is the cooking apparatus (stove). You are like the system bus (moving things around, etc...). So when you boot a computer, you take your basic ingredients out of storage and put them on the counter (loading the OS). This is a loose example, but it works well.
Now to move into OOP: an ingredient is an object, so is a tool (bowl, knife, spoon, etc...). Each one of these has properties (knife= handle_color: black, blade_type: serrated, etc...). And each one has methods/actions that you can perform with them (knife = cut(pepper)).
Now you can take this as far as you want to. For instance, there are green, yellow and red peppers. Each one is a pepper, so you can say "inherit the pepper class" (layman: take everything you know about a pepper and apply it to this specific pepper, pepper has a color attribute, a red pepper is color=red).
You can even separate class from instance (this particular pepper is an instance, whereas on the recipe card it's a class).
So you could make some pseudocode:
class pepper {
var color
var spiciness
var size
}
class redPepper extends pepper {
construct(){
$this->color=red
}
}
class cuttingKnife extends knife{
construct(){
$this->blade_type=serated
}
}
class cookingPot extends pot{
construct(){
//We all know what a cooking pot is
}
}
class stove extends apparatus{
construct(){
//We all know what a stove is
}
}
$knife = new cuttingKnife();
$myPepper = new redPepper();
$pot = new cookingPot();
$stove = new stove();
$knife->cut($myPepper);
$pot->putOn($stove);
$stove->cookOn("high");
$pot->putIn("water");
$pot->putIn($myPepper);
//This will boil a cut pepper
Of course, people won't necessarily understand the pseudocode, but they would understand how to boil something. They would understand the difference between a "pepper" and a "red pepper". I think you can pretty much use this analogy for any computer related thing with some minor tweeks.
- multithreading: add more burners to the stove and another cook in a single kitchen
- multicore arch.: add a second kitchen
- downloading/installing software: go to store, find food, bring home, deposit in storage
- partitioning a HDD: different cabinets/fridge could be Linux proc system (because it's special).
Etc...
回答5:
Interface: The buttons of the remote control. Users know how these buttons are supposed to function.
Concrete class: Toshiba RC, Philips RC, JVC RC - what's inside the box is the concrete implementation.
回答6:
Abstract class: The stencil a tailor uses in order to create a Made to measure garment. While You can't wear the stencil itself it is used to produce suits You can wear - the suits are "derived" from the stencil.
Interface: A dress code.
回答7:
A good example is a calculator. Inside a calculator is a circuit board that has connections between its display, buttons, and a logic processor.
The circuit board acts like an abstract class. It provides the plumbing for any calculator built with it. In addition, it has certain interfaces that connect to a display, to an array of buttons, and to a logic processor.
In turn, any display manufactured to work with the circuit board must have a connector that fits the display interface on the circuit board. The same goes for the buttons and the logic processor, the latter likely having a certain arrangement of pins that align with the interface on the circuit board.
A developer using OOD would create an abstract class, CalculatorBase, to define the plumbing between the buttons, the display, and the internal logic. The abstract class would also specify how derivative classes use this plumbing to respond to certain events.
CalculatorBase, however, wouldn't depend on a specific display, a specific set of buttons, or even a specific implementation of logic. Instead, the developer specifies an interface for each, such as ICalculatorDisplay, for example. ICalculatorDisplay would specify how CalculatorBase expects to interact with a display. CalculatorBase would then work with any display that implements ICalculatorDisplay.
回答8:
(In some languages, abstract class is used the same way as an interface, so it may be confusing)
A handful of classes that all have a certain common interface is like a handful of words that can fill in the the blank in a sentence. Example:
- ____ has wings
- Chicken has wings
- Airbus A320 has wings
However, the classes themselves, while they can all fit the blank in the sentence, do not have any relatioship in between. Chicken is a fowl while Airbus A320 is an aircraft. The only commonality is that they both have something that we call "wings". (You can also say that the true meanings of the "wings" are different in the two situations.)
class IHasWings : public IUnknown
{
public:
// IUnknown methods: (Inherited)
// IHasWings methods:
virtual HRESULT GetWingSpan([out] double* pdblWingSpan) = 0;
virtual HRESULT IsWingMovable([out] BOOL* pIsMovable) = 0;
virtual HRESULT IsWingDetachable([out] BOOL* pIsDetachable) = 0;
};
class Chicken : public ... ..., public IHasWings
{
};
class AirbusA320 : public ... ..., public IHasWings
{
};
回答9:
Very simply put, an interface defines how you can talk to me.
Whereas an abstract class could define one of my talents such as playing the guitar. The problem is that "playing guitar," by itself isn't really that useful. But we could use this ability to create a type of person, such as a musician (which we could say is a class).