Interface vs abstract class

Started by
13 comments, last by way2lazy2care 12 years, 5 months ago
could anyone give me an example code snippet of when they would use a interface class vs and abstract class and the PURPOSE/INTENDED usage of both. I've googled and read and am having a hard time understanding the difference. Imhopeing a simple example can enlighten me!
Advertisement

could anyone give me an example code snippet of when they would use a interface class vs and abstract class and the PURPOSE/INTENDED usage of both. I've googled and read and am having a hard time understanding the difference. Imhopeing a simple example can enlighten me!


Which language are you using?
Depends on the language you're using. Some don't have interfaces, some interfaces behave differently.

C# is the common language where both exist and are different. In C#, you use interfaces until interfaces aren't sufficient (you need fields, you need some common constructor behavior, some default method implementation.... anything else interfaces can't do). Then you use an abstract class.

Their purpose in C# are the same, but interfaces restrict what you can do to allow safe/sane multiple inheritance.



Their purpose in C# are the same, but interfaces restrict what you can do to allow safe/sane multiple inheritance.


That last point is key. C# only allows you to inherit from a single class, but you can implement as many interfaces as you'd like.

While in C++ interfaces as a 'thing' don't exist. You have abstract classes, which are classes with one or more pure virtual functions, which is a function without an implementation, meaning you have to inherit and implement that function to be able to use the class. The closest C++ has to an interface is a class declared with 100% pure virtual methods.

If it is C++ you are interested in, my most recent tutorial chapter covers exactly this topic while introducing the Service Provider pattern, a great alternative to a billion and one global “manager" classes, another hot button issue around here lately. So if you want to see a pure virtual C++ class in action, check that link out.

The only real difference between an interface and an abstract class is the interface is 100‰ free of implementation, while the abstract class may have some implementation which can be inherited. Neither class can be instantiated ( new ed ) directly, both need to be inherited and the pure virtual methods implemented before use.
Just to chime in my 2 cents here I'm going to try to explain what has already been said in some simpler terms. Basically an interface is a class that declares functions with no code inside of them. The point is that you can use it like a template if you will. However like Talestyne says above you are limited. Because of this nature of the interface you can not declare object members or provide default functionality to the methods. In most of my experience there's not a lot of real world instances where you would want or need to use an interface as most of the time there is common or default functionality that like objects should have.

An abstract class can be thought of as the successor to interface classes (an Interface++ if you will). Abstract classes like an interface class are basically a template used for it's derivatives, so like Serapth says you can not create a new instance of either. However the added benefits are that now you can also declare class members and base or default functionality within the methods. In my experiences these are always preferred as it allows you to tie your common functionality together in the base class (the abstract), add additional functionality to the derivatives (the classes that inherit from the abstract) yet still fall back or utilize what is written in the abstract.

For just a very quick example lets think of Sprite objects that might be used in a game. They would all want a draw method, this is where either an interface or an abstract comes in handy. You can define the base object that declares this draw method, then your PlayerSprite and ComputerSprite objects can inherit from the base object and they both would have the known draw method. However you would probably also want to add in some members like velocity, life and so on. In most if not all cases these are some numeric data type that can be altered or read from and would exist in all sprites. With the interface object your out of luck. You will need to declare these members for every sprite individually. This is why I almost always prefer the abstract class. In an abstract class you can declare the additional members as needed and also you could write a basic constructor that would initialize these members. Now any derivative Sprite object you write can call back to the base objects constructor to automatically instantiate and set these values. Less coding you have to do on every other sprite object you create.

Dan Mayor

Professional Programmer & Hobbyist Game Developer

Seeking team for indie development opportunities, see my classifieds post

In some languages where virtual member functions are treated specially, sometimes there are performance arguments to make about using an abstract base class over an interface or pure virtual class.

There is often a good argument to be made for splitting such a class into the virtual and non-virtual components, to reduce coupling.

In most of my experience there's not a lot of real world instances where you would want or need to use an interface as most of the time there is common or default functionality that like objects should have.
[/quote]
You can still achieve this. You make your interface, then you provide a default implementation. Client classes can choose whether or not to extend this default implementation, or preferably to use composition, when implementing the interface.


For just a very quick example lets think of Sprite objects that might be used in a game ... However you would probably also want to add in some members like velocity, life and so on. In most if not all cases these are some numeric data type that can be altered or read from and would exist in all sprites. With the interface object your out of luck. You will need to declare these members for every sprite individually.
[/quote]
But eventually you'll create sprites that have no life value, or don't move, and you'll be forced to deal with these aspects because they have been intrinsically coupled to the notion of being a sprite.

So you'll get situations where you set the health to an absurd value, only to find a bug sometime because the non-living sprite landed in a fire pit and eventually exhausted its health. Then you might redefine negative heath to mean infinite health, or add a boolean value indicating whether a sprite takes damage. You must now carefully write the code that health can only go from positive to zero, and not turn negative. Or your base class will have a bunch of conditional statements, and functions that can do nothing for classes created in a certain state (void takeDamage(float damage) { if (invulnerable) { return; } ... }).


Less coding you have to do on every other sprite object you create.
[/quote]
Again, by separating the interface from a basic/default implementation, you don't require more code. It is just as easy for the clients to use the basic/default implementation. It gives the flexibility to ignore the default implementation if it is unsuited. It is easier to unit test classes using the interface.
rip-off could you give a more detailed example of what you mean, specifically about composition? How does this help you get around the issue you mention of all classes inheriting stuff they don't need? Would you control vars purely through methods so if the method is blank nothing happens?

Man structure stuff twists my melon :blink:
Let us take the given example written in some fictional language, written using an abstract base class:

type Sprite {

public Sprite(filename, ...) {
// Reasonable defaults
}

public void draw(Renderer renderer) {
if(health > 0 || invulnerable) {
renderer.draw(image, position)
}
}

public void update() {
position += velocity
}

protected void setInvulnerable() {
invulnerable = true
}

private Image image
private Vec2 position
private Vec2 velocity
private int health
private bool dead
private bool invulnerable
}

type Mario inherits Sprite {

Mario() {
super("mario.png", ...)
}

// ...

}

type Crate inherits Sprite {

Crate() {
super("crate.png", ...)
setInvulnerable()
}

}

Now, let us look at the same thing except having an interface, a basic implementation of this interfaces and some examples of the above classes. First, our interface and basic implementation:

interface Sprite() {

public void draw(Renderer renderer)

public void update()

}

type SimpleSprite inherits Sprite {

public SimpleSprite() {
// Reasonable defaults
}

public void draw(Renderer renderer) {
if(health > 0 || invulnerable) {
renderer.draw(image, position)
}
}

public void update() {
position += velocity
}

protected void setInvulnerable() {
invulnerable = true
}

private Image image
private Vec2 position
private Vec2 velocity
private int health
private bool dead
private bool invulnerable
}


Here is a really simple implementation of Mario, really just as simple as the first.

type Mario inherits SimpleSprite {

Mario() {
super("mario.png", ...)
}

// ...

}


Here is one using composition, if the programmer wants.

type Mario inherits Sprite {

Mario() {
sprite = new SimpleSprite("mario.png", ...)
}

public void draw(Renderer renderer) {
sprite.draw(renderer)
}

public void update() {
sprite.update()
}

private SimpleSprite sprite

}


But our Crate implementation can ignore the SimpleSprite and just implement what it needs:

type Crate inherits Sprite {

Crate(position) {
this.image = new Image("crate.png")
this.position = position
}

public void draw(Renderer renderer) {
renderer.draw(image, position)
}

public void update() {
// Do nothing...
}

private Image image
private Vec2 position
}

Note the new Crate class doesn't need to worry about marking itself as invulnerable.


Would you control vars purely through methods so if the method is blank nothing happens?
[/quote]
I don't understand the question. I generally write code such that the class members cannot be accessed outside the class. For example, I would prefer to use private variables and protected accessor/mutators in an inheritance hierarchy, if I needed to.
One not mentioned thing about interfaces is that they are often used to add a certain specific trait to a bunch of unrelated objects that allow another unrelated system to do stuff with those unrelated objects.

For instance the IComparable interface in C# is a way of saying that your class objects can compare to other objects of the same class in such a way that they can be ordered allowing you access to a bunch of useful functions on C#'s generic containers.

Interfaces are also a little less dangerous than multiple class inheritance because class inheritance can also inherit default functionality and members that you might not have been aware of. Abstract classes are like dangerous interfaces; as technically there is no such thing as a "pure abstract class" as a language feature you can only give the guarantees of an abstract class, which can still have implementation details and members that you may not want in your sub-class and could actually be harmful. The concept of a pure abstract class, a class with no implementation details at all just abstract functions, is essentially the same as an interface other than the fact that there's nothing that guarantees that a pure abstract class is actually pure for the people that use it.

One not mentioned thing about interfaces is that they are often used to add a certain specific trait to a bunch of unrelated objects that allow another unrelated system to do stuff with those unrelated objects.


This muddies the waters, and I would argue is not correct. Interfaces contain no logic, so never really 'add' anything to object. Interfaces are used to provide access to common functionality across different classes. The objects are related by this common interface.

To add specific traits, you need a language with traits or Mixins. These structures are similar to interfaces (and replace them in certain languages), but using the term 'interface' for that behavior is not really accurate.

This topic is closed to new replies.

Advertisement