7

Just the 5 minute overview would be nice....

abatishchev
  • 98,240
  • 88
  • 296
  • 433
  • 4
    This does not appear to meet the requirements for 'not a real question.' – Jeff Sternal May 20 '10 at 18:17
  • 9
    There's no reason to close this question. While it's not wordy, the question asked is exact, and not ambiguous. – Igal Tabachnik May 20 '10 at 18:17
  • 2
    Umm closing this was a little harsh. – Dan Blair May 20 '10 at 18:18
  • If you notice you have a few classes inheriting from a base class that not only never gets instantiated but also has many stub methods defined to `throw new Exception("You need to inherit from this class and implement this method");`, those methods should be abstract, as should the class. – Brian May 20 '10 at 19:42
  • State pattern all the way down! *Abstract methods are used a lot for polymorphic behavior*. –  May 20 '10 at 20:16
  • The question makes no sense. The subject does not correspond to the content. – bmargulies May 20 '10 at 20:45
  • 1
    See [Technical reason for using Abstract Classes in C#/Java](http://stackoverflow.com/questions/1186092/technical-reason-for-using-abstract-classes-in-c-java) – Matthew Flaschen May 21 '10 at 03:20
  • Please approve one of the answers – abatishchev Apr 23 '11 at 08:19

11 Answers11

10
public abstract class MyBaseController {
    public void Authenticate() { var r = GetRepository(); }
    public abstract void GetRepository();
}
public class ApplicationSpecificController {
    public override void GetRepository() { /*get the specific repo here*/ }
}

This is just some dummy code that represents some real world code I have (for brevity this is just sample code)

I have 2 ASP MVC apps that do fairly similar things. Security / Session logic (along with other things) happens the same in both. I've abstracted the base functionality from both into a new library that they both inherit. When the base class needs things that can only be obtained from the actual implementation I implement these as abstract methods. So in my above example I need to pull user information from a DB to perform authentication in the base library. To get the correct DB for the application I have an abstract GetRepository method that returns the repository for the application. From here the base can call some method on the repo to get user information and continue on with validation, or whatever.

When a change needs to be made to authentication I now only need to update one lib instead of duplicating efforts in both. So in short if you want to implement some functionality but not all then an abstract class works great. If you want to implement no functionality use an interface.

Justin
  • 4,434
  • 4
  • 28
  • 37
9

Just look at the Template Method Pattern.

Jordão
  • 55,340
  • 13
  • 112
  • 144
7
public abstract class Request
{
   // each request has its own approval algorithm. Each has to implement this method
   public abstract void Approve();

   // refuse algorithm is common for all requests
   public void Refuse() { }

   // static helper
   public static void CheckDelete(string status) { }     

   // common property. Used as a comment for any operation against a request
   public string Description { get; set; }

   // hard-coded dictionary of css classes for server-side markup decoration
   public static IDictionary<string, string> CssStatusDictionary
}

public class RequestIn : Request
{
   public override void Approve() { }
}

public class RequestOut : Request
{
   public override void Approve() { }
}
Sarah Vessels
  • 30,930
  • 33
  • 155
  • 222
abatishchev
  • 98,240
  • 88
  • 296
  • 433
  • Why do you do this as an abstract method rather than as an interface? Is it just lighter-weight if you've only got a couple of things implementing Request? – Tom Womack May 20 '10 at 18:05
  • 6
    How is this a real world example? – Oded May 20 '10 at 18:05
  • 2
    An abstract class can implement methods, so you might have some default behavior there that a descendant would call into... you can't do this with an interface. – Justin Ethier May 20 '10 at 18:07
  • @Tom Womack: I edited my answer. Super-class contains common properties and methods and abstract stubs for sub-classes to implement. – abatishchev May 20 '10 at 18:10
  • @Oded: This classes are used in my accounting software. – abatishchev May 20 '10 at 18:11
  • 4
    @Tom Womack - An abstract method doesn't have to be parts of the public interface. An Interface does. – Dan Blair May 20 '10 at 18:16
  • @abatishchev - in that case, an introduction to the code is in place. Something to the tune of "I am using this in my accounting software" and explain what the value of doing so is. – Oded May 20 '10 at 18:18
  • @Oded: I added comments to my classes' members – abatishchev May 20 '10 at 18:21
1

Use of abstract method is very common when using the Template Method Pattern. You can use it to define the skeleton of an algorithm, and have subclasses modify or refine certain steps of the algorithm, without modifying its structure.

Take a look at a "real-world" example from doFactory's Template Method Pattern page.

Igal Tabachnik
  • 31,174
  • 15
  • 92
  • 157
1

The .NET Stream classes are a good example. The Stream class includes basic functionality that all streams implement and then specific streams provide specific implementations for the actual interaction with I/O.

Dan Bryant
  • 27,329
  • 4
  • 56
  • 102
1

The basic idea, is to have the abstract class to provide the skeleton and the basic functionality and just let the concrete implementation to provide the exact detail needed.

Suppose you have an interface with ... +20 methods, for instance, a List interface.

List {interface }
    + add( object: Object )
    + add( index:Int, object: Object )
    + contains( object: Object ): Bool
    + get( index : Int ): Object
    + size() : Int 
    ....

If someone need to provide an implementation for that list, it must to implement the +20 methods every time.

An alternative would be to have an abstract class that implements most of the methods already and just let the developer to implement a few of them.

For instance

To implement an unmodifiable list, the programmer needs only to extend this class and provide implementations for the get(int index) and size() methods

AbstractList: List
    + get( index: Int ) : Object { abstract }
    + size() : Int { abstract }
    ... rest of the methods already implemented by abstract list

In this situation: get and size are abstract methods the developer needs to implement. The rest of the functionality may be already implemented.

EmptyList: AbstractList 
{
     public overrride Object Get( int index ) 
     {
          return this;
     }
     public override int Size() 
     {
          return 0;
     }
}

While this implementation may look absurd, it would be useful to initialize a variable:

  List list = new EmptyList();

   foreach( Object o: in list ) {
   }

to avoid null pointers.

OscarRyz
  • 196,001
  • 113
  • 385
  • 569
0

Used it for a home-made version of Tetris where each type Tetraminos was a child class of the tetramino class.

David Brunelle
  • 6,528
  • 11
  • 64
  • 104
0

You might use an abstract method (instead of an interface) any time you have a base class that actually contains some implementation code, but there's no reasonable default implementation for one or more of its methods:

public class ConnectionFactoryBase {

    // This is an actual implementation that's shared by subclasses,
    // which is why we don't want an interface
    public string ConnectionString { get; set; }

    // Subclasses will provide database-specific implementations,
    // but there's nothing the base class can provide
    public abstract IDbConnection GetConnection() {}

}

public class SqlConnectionFactory {
    public override IDbConnection GetConnection() {
        return new SqlConnection(this.ConnectionString);
    }
}
Jeff Sternal
  • 47,787
  • 8
  • 93
  • 120
0

For instance, assume you have some classes that corresponds to rows in your database. You might want to have these classes to be considered to be equal when their ID is equal, because that's how the database works. So you could make the ID abstract because that would allow you to write code that uses the ID, but not implement it before you know about the ID in the concrete classes. This way, you avoid to implement the same equals method in all entity classes.

public abstract class AbstractEntity<TId>
{
    public abstract TId Id { get; }

    public override void Equals(object other) 
    {
         if (ReferenceEquals(other,null)) 
             return false;
         if (other.GetType() != GetType() ) 
             return false;
         var otherEntity = (AbstractEntity<TId>)other;
         return Id.Equals(otherEntity.Id);
    } 
}
driis
  • 161,458
  • 45
  • 265
  • 341
0

I'm not a C# guy. Mind if I use Java? The principle is the same. I used this concept in a game. I calculate the armor value of different monsters very differently. I suppose I could have them keep track of various constants, but this is much easier conceptually.

abstract class Monster {
    int armorValue();
}

public class Goblin extends Monster {
    int armorValue() { 
        return this.level*10;
    }
}

public class Golem extends Monster {
    int armorValue() {
        return this.level*this.level*20 + enraged ? 100 : 50;
    }
}
corsiKa
  • 81,495
  • 25
  • 153
  • 204
  • 1
    As written, your example provides a justification for using an interface, but no justification for using an abstract class. – Brian May 20 '10 at 19:33
  • I suppose I could have put in 20 more lines of code to make it more verbose. I also see how I could have used an interface like Attackable that would have (amongst others) armorValue() as a member. However, I still feel this illustrates the point quite well: both Goblins and Golems have an armor value, but it needs to be calculated differently. – corsiKa May 20 '10 at 19:40
0

An example

namespace My.Web.UI  
{  
    public abstract class CustomControl : CompositeControl  
    {
        // ...

        public abstract void Initialize();

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            // Anything custom

            this.Initialize();
        }
    }
}
BrunoLM
  • 97,872
  • 84
  • 296
  • 452