Abstract Classes and Interfaces

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

User avatar
Jach
Posts: 167
Joined: Sat May 05, 2007 8:38 pm UTC
Contact:

Abstract Classes and Interfaces

Postby Jach » Sat Sep 15, 2007 1:43 am UTC

I was talking to someone earlier today about them, because he's learning about them in Java. I've been there, but the book and teachers basically just told me what the syntax was and how to use them, not really what good they are.

Can someone here enlighten me on any possible usefulness of abstract classes and interfaces? The only useful thing I've been able to glean from them is documenting your code and forcing a class to behave a certain way.
I love reading quotes.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Postby EvanED » Sat Sep 15, 2007 2:24 am UTC

Interfaces are essential (in Java) for providing a way to implement certain features. This is really vaguely (read: poorly) worded, so perhaps a couple examples are in order. (I'm not actually convinced the rest of this is clearer than mud, so feel free to ask for clarification or just say "your explanation sucks" ;-))

If you want to create a new thread, you write a class that implements the Runnable interface. This interface consists of a single function called run() which is the first function called in the context of the new thread. Other code needs to know what function to call when starting the thread; it solves this issue by always calling a function called "run". Because Java requires stuff to be statically typed, it needs to be able to determine at compile time that a particular class contains a run method; it does this by requiring you to implement the interface runnable.

A similar example is used all around GUI stuff. When the user clicks a button, the Swing framework needs to call a function of yours that will react to the button press in whatever way you want. Again, it does this by requiring that you (1) name that function buttonClick* and (2) satisfy the type system by implementing the interface ButtonClickListener*.

(* Note: I made these names up. But the idea is right.)


Abstract classes can be useful for some of the same sorts of things, except that you may provide implementations of some functions. Often this can simplify code. For instance, a lot of the Listener classes in Swing have more than one method. For instance, I think there's something like WindowListener (again, the name is invented) that has functions that are called when a window is resized or moved. So there is a windowMoved() function that you have to implement as well as a windowResized() function. But say that you don't care if the user moves the window; it's pretty rare that that affects anything. But resizing is something that often you do care about: you may need to redraw the screen. But if you implement WindowListener, you have to provide an implementation of both functions. (See below for more discussion on this.) So Java also provides a class called WindowAdapter that implements both of these functions as no-ops, and you only need to implement the one you care about. In other cases, such as the thread example above, there are other syntactic conveniences that can come about by the use of a base class instead of an interface.

There's another big reason for abstract classes which I'll get to in a second, but I first want to answer a question "why not always use abstract classes if they can do the same things but the classes provide easier syntax?" The answer is that they don't do the same thing. For instance, say I have a class Foo that inherits from class Bar. If Foo represents a window, I can't subclass WindowAdapter instead, because Java doesn't support multiple inheritance. Same deal with threads. By contrast, I can implement however many interfaces as I want, so I can have Foo subclass Bar and implement WindowListener. Same deal with the thread example. Thus Java provides both the base class and the interface versions so that you can use the cleaner base class approach when it's possible and the interface approach other times.


(I should also say that there are other ways of solving this sort of problem that I think are significantly better. For instance, C# includes something called delegates. These allow you to say stuff like "create a new thread and start it calling the function startingInANewThread", or "when the user clicks a button call the function theUserClickedThisButton". This lets you name the functions whatever you want (instead of forcing you to use run() and buttonClicked()) and gets rid of some of the other annoyances of the Java approach.)


The other use for abstract classes is to add restrictions to an inheritance hierarchy. For instance, say you need to represent vehicles of some sort. You may have a Vehicle class, a Car class, a Plane class, and Boat class. Maybe there is a Honda class that is a subclass of Car, and a Accord class that is a subclass of Honda. Now, it's pretty clear what an instance of an Accord is. But if I say "Vehicle v = new Vehicle()", what is v? In the real world, there's no such thing as a generic vehicle, so this statement makes no sense. If I say "[sudo ;-)] give me a vehicle" and you oblige, I'll always be able to find a better description of it: it's a J/22 sailboat, or it's a Boeing Dreamliner, which in our examples would all be subclasses of Vehicle.

Because you can't have just a vehicle, depending on how well the program is supposed to model reality, you may want to disallow statements like "Vehicle v = new Vehicle();", and to do so you make Vehicle abstract.

Rysto
Posts: 1460
Joined: Wed Mar 21, 2007 4:07 am UTC

Postby Rysto » Sat Sep 15, 2007 2:30 am UTC

They're central to the idea of object-oriented programming. Let's take the java.util.Map interface as an example. The interface specifies a set of operations that we can perform on objects that implement the interface. This means that we can write code that takes a Map as input and do work with it without caring how the Map actually performs the operations. This allows us to write code that could work equally well on hash tables and binary search trees.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Postby EvanED » Sat Sep 15, 2007 2:41 am UTC

Rysto wrote:They're central to the idea of object-oriented programming. Let's take the java.util.Map interface as an example. The interface specifies a set of operations that we can perform on objects that implement the interface. This means that we can write code that takes a Map as input and do work with it without caring how the Map actually performs the operations. This allows us to write code that could work equally well on hash tables and binary search trees.


Because I think my spiel was pretty poorly explained, this works into what I said in the first half. I didn't really say what Rysto said, with the "without caring how the Map actually performs the operations" bit, which is really the key to the issue, so I left out a big part. But this is related to what I was saying with callback functions.

Let's say that you have a function foo that needs to operate on something that acts like a map. It wants a way to add something to the map and remove it to the map.

The Map interface has two functions: put(object, object) and get(object). (I actually bothered to look in the Javadoc this time.)

Implementing the Map interface means that you write the put and get functions for your object. foo then takes as a parameter a Map (precisely, it takes an object whose class implements the Map interface), and can call the put and get functions.

[The put and get functions act as callbacks, in that the function foo just needs to have references to the functions through the interface and calls them, without caring exactly what they do.]

I don't think this post actually helps matters, so maybe I should leave the thread. ;-)

jzamor
Posts: 2
Joined: Sat Sep 15, 2007 7:27 am UTC

A little clearer

Postby jzamor » Sat Sep 15, 2007 8:38 am UTC

So sure, abstract classes and interfaces are built around the central idea of polymorphism, but that alone doesn't really explain the difference between the two.

First understand of course that interfaces can not have code (implement methods), while an abstract class can (not all methods in an abstract class must be abstract).

Second also be aware that Java, unlike C++, does not support multiple-inheritance.

Third understand that an object is an instantiation of a class. And a class represents a type.

The idea of a type is key. An interface (not necessarily the Java interface keyword) defines a type. That is the sum of what is exposed to its client.

So... Any class is essentially a type. A class hierarchy (e.g. class A extending class B) defines a hierarchy of types. So if class A extends class B, we can think of class A (or type A) as being also of type B.

A hierarchy of classes is great. We can build new types from old types. Weather you do this with a normal class or an abstract class is really irrelevant as far as the distinction between the abstract class and java interface is concerned. Remember both may implement methods.

The Java interface is actually a workaround for the Java limitation of multiple-inheritance. A Java class may only extend one super class, but a Java class may implement as many Java interfaces as it pleases. This allows you to define a type built from many other distinct types. So if I had types A, B, C and D. And then I created a Java class Z that implemented the interfaces A, B, C and D, then an object instantiated from class Z would also be of types A, B, C and D.

So really the reason Java has abstract classes and interfaces is simply because the designers of Java didn't want programmers to be able to shoot themselves in the foot so easily with multiple-inheritance, as C++ allows. To understand this more, I suggest you research multiple inheritance and the tricky situations that can arise because of it. In short though: in practical applications it's more pain then it is generally worth.

At this point you may be wondering then why abstract classes exist at all. Abstract classes are really just classes that aren't fully implemented yet and therefore can't be instantiated. Of course we just saw that they represent a type, but a type for which the implementation details don't fully exist (but may exist in part). This however is really a separate issue from Java interfaces all together.

Hope this helps.

recurve boy
Posts: 353
Joined: Wed Jan 31, 2007 5:48 am UTC
Location: Sydney Australia
Contact:

Re: Abstract Classes and Interfaces

Postby recurve boy » Sat Sep 15, 2007 2:42 pm UTC

Jach wrote:Can someone here enlighten me on any possible usefulness of abstract classes and interfaces? The only useful thing I've been able to glean from them is documenting your code and forcing a class to behave a certain way.


Easy examples have been said. We can have a class of objects that are similar in the methods that are exposed. In the given case Map. Now depending on the data we have, the precise implementation of a particular map can affect performance. So we can pick the appropriate map to use, but the code that requires this data structure doesn't care. It can treat all maps the same.

A more interesting example is testing. I came up with this idea independently at uni, but later I learned it is commonly referred to as inversion of control. If you have a field that is an object. Instead of instantiating this object in the the containing object, we can have getter and setter methods. So if a contains b, we have a setB() and getB() methods. Now say we declare b as it's interface i. So really we have a getI() and a setI(). Now, if we want to test our a class independent of b (because we are only interested in logic mistakes in a at the moment), we can implement a dummy class (mocking) d that implements i but only returns trivial results. That is, we can test a in isolation and thus we can be sure that there are no logic mistakes in b affecting a.

User avatar
Jach
Posts: 167
Joined: Sat May 05, 2007 8:38 pm UTC
Contact:

Postby Jach » Sun Sep 16, 2007 8:25 pm UTC

Thanks all, I think I understand better now. Unfortunately I still see no practical use in my daily coding. xD I know part of it is my dislike for the purist approach to OOP; I like functional programming too much, and I've gotten used to doing the Python way of things as opposed to the Java/C++ way. (For example, no one really cares if you do object.variable syntax and using a get() method for that is laughable.)
I love reading quotes.

User avatar
yy2bggggs
Posts: 1261
Joined: Tue Oct 17, 2006 6:42 am UTC

Postby yy2bggggs » Sun Sep 16, 2007 9:38 pm UTC

Jach wrote:Thanks all, I think I understand better now. Unfortunately I still see no practical use in my daily coding. xD I know part of it is my dislike for the purist approach to OOP; I like functional programming too much, and I've gotten used to doing the Python way of things as opposed to the Java/C++ way. (For example, no one really cares if you do object.variable syntax and using a get() method for that is laughable.)


What's so great about OOP:
http://www.research.att.com/~bs/bs_faq.html#oop

Oh, and C++ isn't an object oriented programming language. If you were told you had to write a get method because that's the C++ way, someone lied to you (and please don't tell me it was a professor either):
http://www.research.att.com/~bs/bs_faq. ... d-language

Also, I've been coding in C++ for a while, and I'm heavily involved in C++ (and currently on a quest to try to completely master it, collect references, etc), but don't take this to mean I think C++ is the only/best language. Nevertheless, C++'s creator, Bjarne Stroustrup, is a very sharp guy and on top of his stuff. I particularly like him because he's not only very technical, he's a pragmatist as opposed to an idealist.

As such, I encourage you to read through his home page.

User avatar
Number
Posts: 63
Joined: Thu Aug 02, 2007 5:42 am UTC
Location: Earth. supposedly

Postby Number » Mon Sep 17, 2007 1:29 am UTC

jzamor wrote:Abstract classes are really just classes that aren't fully implemented yet and therefore can't be instantiated.

Interesting statement, this one. Here I bring up the anonymous class in Java. Use this declaration for absClass (please excuse any errors due to java 6 - I learned under java 4):

Code: Select all

public abstract class absClass
{
   public int method1();
   public int method2() {return 42;}
}

and compile this inside your main method:

Code: Select all

absClass obj = new absClass(){int method1(){return 6*9;}};
System.out.println(obj.getClass().getName() + "\n" + obj.method1())

The result will be some anonymous class name. Especially in GUI programming, you see code like the above all the time, often with something like new Runnable() {public void run() {...}};

As far as I know, interfaces and abstract classes are for confusing those who should not take AP Comp Sci AB and for providing the teachers with even more pointless exercises :). I think abstract classes are more for the programmer than for the compiler/interpreter (nod to jzamor), since simply providing a compatible but useless method body allows you to make your abstract class concrete (if that's what non-abstract classes are called). Maybe abstract classes allow for some compiler optimizations or something like that, as well.
You live and learn. At any rate, you live.

Kelmi
Posts: 2
Joined: Mon Sep 17, 2007 12:45 pm UTC

Postby Kelmi » Mon Sep 17, 2007 12:56 pm UTC

Number wrote:Here I bring up the anonymous class in Java. Use this declaration for absClass (please excuse any errors due to java 6 - I learned under java 4):

Code: Select all

public abstract class absClass
{
   public int method1();
   public int method2() {return 42;}
}

and compile this inside your main method:

Code: Select all

absClass obj = new absClass(){int method1(){return 6*9;}};
System.out.println(obj.getClass().getName() + "\n" + obj.method1())

The result will be some anonymous class name.


The code creates an anonymous class and obj will be an instance of this class. The anonymous class is a child of absClass.

You still can't instantiate an abstract class.

GUI programming in Java is just plain disgusting. No-one wants to fully implement large interfaces and so we need these stupid "adapter"-classes etc. All this trouble just because of the lack of function pointers.

User avatar
Hench
Porn, hence, Man
Posts: 498
Joined: Wed Mar 28, 2007 4:16 pm UTC
Location: Right between my eyes
Contact:

Postby Hench » Tue Sep 18, 2007 6:19 pm UTC

I'm not a terribly big fan of creating anonymous object classes like that; I find it mucks up the code and creates unnecessary class files. Implementing the Listener classes and creating empty methods avoids cluttering the class files but does have the side effect of having a bunch of empty methods in the main class file. It's a fair trade off in my opinion.

That said, Java's Swing implementation isn't perfect, but the facts that it's modular and it's so easy to create custom GUI elements make it very nice and relatively simple to create a functional and nearly-native looking (on Windows, at least) app.

And I never used abstract classes or interfaces very much myself until recently when I started coding actual industrial-use applications - abstract classes and inheritance made my life much easier when integrating the back-end into the GUI. Instead of writing methods for every instance of the subclass specific objects I used, I was able to write generic code because I could guarantee that the subclasses contained and implemented the specific methods. The newly implemented enums also came in handy to create type-safe parameters.
Spoiler:
Your perceptions will not change reality, but simply color it.

Zanik221
Posts: 47
Joined: Sat Mar 17, 2007 12:38 am UTC

Postby Zanik221 » Tue Sep 18, 2007 8:26 pm UTC

Number wrote:As far as I know, interfaces and abstract classes are for confusing those who should not take AP Comp Sci AB and for providing the teachers with even more pointless exercises :). I think abstract classes are more for the programmer than for the compiler/interpreter (nod to jzamor), since simply providing a compatible but useless method body allows you to make your abstract class concrete (if that's what non-abstract classes are called). Maybe abstract classes allow for some compiler optimizations or something like that, as well.

The reason you need abstract methods is so that you actually call the correct methods when using polymorphism. I can best explain this with a simple example.

Code: Select all

abstract class A {

          abstract int one();

          int two() {
                    return 1;
          }
}

class B extends A {

          B() {
          }

          int one() {
                    return 1;
          }

          int two() {
                    return 2;
          }
}

Now, when using polymorphism, the two() method would behave in an potentially unwanted manner.

Code: Select all

A a = new B();
System.out.println(a.two());

Even though the reference is to a B object, this will still call A's two() method. However, the one method, because it's abstract in A, would be call B's if the object were referenced like this.

Abstract classes like this are useful when you have several object with only differ in the operation of some functions. For example, in one of my early programming classes, we have to make a battleship game. The board was stored as a matrix of 'Cell' objects. From that there were different types of cells. One for water, one for ship, etc. So some functions were exactly the same between them. By making the Cell class abstract, any shared functions only have to be written once.


Interfaces, on the other hand, exist primarily because Java does not allow multiple inheritance. Any given class can only inherit from one class. They can, however, implement as many interfaces as they wish. The idea behind this is to prevent you from inheriting two different methods with the same signature and having them overwrite each other.

Rysto
Posts: 1460
Joined: Wed Mar 21, 2007 4:07 am UTC

Postby Rysto » Tue Sep 18, 2007 8:58 pm UTC

Zanik221 wrote:Now, when using polymorphism, the two() method would behave in an potentially unwanted manner.

Code: Select all

A a = new B();
System.out.println(a.two());

Even though the reference is to a B object, this will still call A's two() method. However, the one method, because it's abstract in A, would be call B's if the object were referenced like this.

No, no, that's totally wrong. Are you confusing abstract with virtual? Abstract is equivalent is a pure virtual function in C++. There is no virtual keyword in Java -- all methods are by default virtual in Java. Java does have the final keyword, which, if you attach it to a method, makes the method non-virtual.

User avatar
Hench
Porn, hence, Man
Posts: 498
Joined: Wed Mar 28, 2007 4:16 pm UTC
Location: Right between my eyes
Contact:

Postby Hench » Tue Sep 18, 2007 9:02 pm UTC

Rysto wrote:
Zanik221 wrote:Now, when using polymorphism, the two() method would behave in an potentially unwanted manner.

Code: Select all

A a = new B();
System.out.println(a.two());

Even though the reference is to a B object, this will still call A's two() method. However, the one method, because it's abstract in A, would be call B's if the object were referenced like this.

No, no, that's totally wrong. Are you confusing abstract with virtual? Abstract is equivalent is a pure virtual function in C++. There is no virtual keyword in Java -- all methods are by default virtual in Java. Java does have the final keyword, which, if you attach it to a method, makes the method non-virtual.


Correct; so in Zanik's example, when you call a.two() it will really call B's two(). That's the whole point.
Spoiler:
Your perceptions will not change reality, but simply color it.

Rysto
Posts: 1460
Joined: Wed Mar 21, 2007 4:07 am UTC

Postby Rysto » Tue Sep 18, 2007 9:28 pm UTC

Rysto wrote:Java does have the final keyword, which, if you attach it to a method, makes the method non-virtual.

Actually, I'd like to clarify this. The final keyword, when applied to a method, means that the method can not be overridden in a subclass. The effect of this is that the JVM can usually treat it as a non-virtual method.

Zanik221
Posts: 47
Joined: Sat Mar 17, 2007 12:38 am UTC

Postby Zanik221 » Tue Sep 18, 2007 10:14 pm UTC

I guess that's what I get for not using Java in so long.

UchihaJax
Posts: 12
Joined: Thu Sep 06, 2007 7:37 pm UTC

Postby UchihaJax » Mon Sep 24, 2007 12:15 pm UTC

Interface specifies the _contract_.
Abstract class specifies both the contract and part of the implementation.

Interfaces are useful if you have an entity that may have completely different implementations (such as saving objects to either a database or a text file, these two could use the IPersister interface but have _completely_ different implementations).

Abstract classes are useful to share common functionality.

MySqlPersister and MsSqlPersister would both inherit from the abstract DatabasePersister, which would handle things like connection strings and other common functionality.

mrkite
Posts: 336
Joined: Tue Sep 04, 2007 8:48 pm UTC

Postby mrkite » Mon Sep 24, 2007 10:56 pm UTC

One place I've used abstract classes:

Widgets. scrollbars, text areas, labels, buttons, they're all widgets.. they all have a width and a height, they all can be added to a container, which is also a widget.

A generic widget can't implement a generic draw method (there's nothing to draw).. every "widget" must implement its own draw() method. Making an abstract Widget class will force anyone building a new "widget" to implement the draw() method.

User avatar
Enssel
Posts: 64
Joined: Mon Sep 24, 2007 10:15 pm UTC

Postby Enssel » Mon Sep 24, 2007 11:11 pm UTC

This may have already been said, but an interface is pretty much the same as a class whose methods are all abstract. I think it was added to Java just to be explicit. Interfaces are also not limited by Java's single inheritance restriction.

pxc
Posts: 62
Joined: Thu Sep 20, 2007 3:20 am UTC

Postby pxc » Tue Sep 25, 2007 4:30 am UTC

Wow. If I were the OP, I'd definitely be at a tl;dr stage right now. Here's the super-duper abridged version (with bold highlights!).

Basically, Interfaces and Abstract classes are handy for grouping things that are alike (follow a set of rules).

The difference is you can actually inherit real, live code from an Abstract class, where implementing an interface is promising to do all of the things the interface says it can.

Hope that helps.

mungojelly
Posts: 4
Joined: Tue Sep 25, 2007 8:54 pm UTC

Postby mungojelly » Tue Sep 25, 2007 10:58 pm UTC

Abstract classes and interfaces are useful not because they advance the immediate concrete purpose of what you're programming, but because they are intentionally vague, undecided & open-ended.

A program that doesn't use this level of abstraction is like the works of a clock: It's made of different objects, but like the gears of the clock they are wedged into each other's teeth, intimate with each other's internal qualities. You can replace one gear with another-- a gold one with a silver one-- but you must make it have very much the same shape in order for it to take the same place in the machine.

A program that does use this level of abstraction is alive & flexible in as many joints as you care to imagine. Each part has not so much a shape as a role, a designated duty, which it is left free to fulfill in its own imaginative ways. Transformations of the state of the program can be not just changes of data, but casting changes, changes of who's doing what when why & how.

This really is how to use abstract classes and interfaces, practically: Write to an interface before even worrying about how you're going to code it. The interface of an object is a much more important (and immutable!) decision than its implementation. Try to believe that objects are interfaces, with some implementation code as a side detail to get the computer to believe in them too. :)

<3

pxc
Posts: 62
Joined: Thu Sep 20, 2007 3:20 am UTC

Postby pxc » Wed Sep 26, 2007 10:51 pm UTC

mungojelly wrote:Abstract classes and interfaces are useful not because they advance the immediate concrete purpose of what you're programming, but because they are intentionally vague, undecided & open-ended.

A program that doesn't use this level of abstraction is like the works of a clock: It's made of different objects, but like the gears of the clock they are wedged into each other's teeth, intimate with each other's internal qualities. You can replace one gear with another-- a gold one with a silver one-- but you must make it have very much the same shape in order for it to take the same place in the machine.

A program that does use this level of abstraction is alive & flexible in as many joints as you care to imagine. Each part has not so much a shape as a role, a designated duty, which it is left free to fulfill in its own imaginative ways. Transformations of the state of the program can be not just changes of data, but casting changes, changes of who's doing what when why & how.

This really is how to use abstract classes and interfaces, practically: Write to an interface before even worrying about how you're going to code it. The interface of an object is a much more important (and immutable!) decision than its implementation. Try to believe that objects are interfaces, with some implementation code as a side detail to get the computer to believe in them too. :)

<3


That was incredible. OP, ignore anything anyone else posted in this thread.

mungojelly: I <3 you.


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 10 guests