Abstract classes

Started by
6 comments, last by JD 19 years, 1 month ago
Can someone explain when it's best to use an abstract class.
Advertisement
When you only care about how to interact with a class and not how it works. For example, my Bomberman clone has an abstract class for the AI. The class is implemented by a DLL. The game doesn't care how the AI works, just that it responds to certain events.
Another example is the DirectX interfaces. They're all abstract classes. You don't care how Direct3D draws a triangle, just that it does it.

Abstract classes come with a very minor overhead, so it's best not to use them everywhere, but there are some places where it's nessecary. If the class is to be implemented in another module (e.g. in a DLL), then you have to use an abstract class, otherwise you'll get compile errors when the compiler can't find the implementation for the class.
If you use the microsoft specific keyword interface they come with no overhead as the vtable for the interface is not generated.

Interfaces are also useful for multiple inheritence. Some poeple don't like the baggage taht multiple inheritence adds for C++. With interfaces you can use multiple inheritence without the worries.

Note: pur virutal classes arent' the same as interfaces in that for pure virtual methods you can define some methods, with interfaces you can't as there is no vtable.

Cheers
Chris
CheersChris
Code Complete, 2nd Edition
Chapter 6.1 - Class Foundations: Abstract Data Types (ATDs)
Page: 126

Buy this book. It's worth the money just for that sub-chapter alone. It's also one of the best books you'll find on software construction (i.e. making software :)).
It helped me to relate abstract objects in programming to abstract objects in the real world. For example (Java code for ease of reading, though this applies to any OO language):
public abstract class Food {  //All food has flavor, but the Food class alone is too general to return a  //specific value  public abstract String getFlavor();}public class RegularPopcorn extends Food {  //RegularPopcorn is specific enough that we can return a flavor for it and  //implement the abstract method  public String getFlavor() {    return "Mmm.  Salt and butter.";  }}public class Spinach extends Food {  //Spinach is also specific enough for us to return a flavor  public String getFlavor() {    return "Yuck, green nasty tasting ickyness.";  }}public abstract class Popsicle extends Food {  //Popsicle is more specific than Food, but there are many flavors of popsicle  //so we leave this class and its getFlavor method abstract}public class FudgeSicle extends Popsicle {  //Here's a more specific form of Popsicle that has a specific flavor we can return  public String getFlavor() {    return "Yum!  Icy, chewy fudge melting in my mouth.";  }}

Abstract methods (which are what make classes abstract) are like gaps in general object types whose implementation must be filled in by a more specific derived class. Like mentioned above, graphics and media devices are often abstract, because they can send output or receive input in different ways.

Another thing that comes to mind is streams. All streams can receive and/or send information from/to a buffer. Thus, a Stream class would have methods for reading and writing the stream. However, a file stream would do this very differently from a memory stream or a TCP socket stream, so the read and write methods are abstract and it's up to the deriving class to decide just how these operations should be accomplished.
Thanx alot for all info. Guess I have some reading to do right now:)
"Design Patterns: Elements of Reusable Software" by Erich Gamma, et. al.

Canonically payroll example. Some payrolls are done every week, some every two weeks, some are done twice a month. The common element is that people are paid according to a schedule, so that is what goes into the interface (the abc).

class IPaySchedule {   public:      virtual date NextPayDate(date today)=0;      virtual ~IPaySchedule() {}};class Weekly : IPaySchedule {   public:      virtual date NextPayDate(date today);};class BiWeekly : IPaySchedule {   public:      virtual date NextPayDate(date today);};class BiMonthly : IPaySchedule {   public:      virtual date NextPayDate(date today);};//From the configuration we decide which payschedule to createstd::string pay_schedule_desc = "BiWeekly";IPaySchedule* pay_schedule = create_pay_schedule(pay_schedule_desc);if( date::today() == pay_schedule->NextPayDate(date::today()) ){//Time to pay people!}


In the real-world you'd probably have sets of people who are paid at different schedules. And the NextPayDate algorithms would be complicated taking into account the configured holidays and weekends.
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
You use them when you have an object A that needs to do something to a general objects of type B and don't care about specific types of the objects under B. Say you have a driver who knows how to work with a generic car steering interface and if there are various makes of cars but all cars implement the same steerable interface then the driver doesn't need to worry about how to specifically driver each car make.

This topic is closed to new replies.

Advertisement