开发者

Please explain the utility of abstract methods in C#

Just the 5 minute ov开发者_StackOverflowerview would be nice....


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.


Just look at the Template Method Pattern.


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() { }
}


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.


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.


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.


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


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);
    } 
}


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;
    }
}


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);
    }
}


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();
        }
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜