Abstract Classes in C#

  • Abstract classes are special type of classes that we can't instantiate.
  • It contains abstract methods/Properties that has no implementation like the methods/Properties that we declare in Interface and it also contains methods/Properties with implementation like normal class.
  • Class deriving from abstact class must provide implementation to the abstract methods/Properties. We have to use override keyword while implementing abstract method in derived class.
  • Like classes we can declare variables, constants, properties, constructors, destructors in abstract classes.
  • We can say that abstract classes are partially like interfaces.
Below is an example of Abstract class.

+
using System;
 
namespace Abstact_Class
{
    public abstract class abstactClass
    {
        //abstract method
        abstract public void abstractMethod();
 
        //normal method with implementation
        public void normalMethod()
        {
            Console.WriteLine("Normal method impemented in abstract class");
        }
    }
 
    public class derivClass:abstactClass
    {
 
        public override void abstractMethod()
        {
            Console.WriteLine("abstract method implemented in derived class");
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            derivClass derivCls = new derivClass();
            derivCls.abstractMethod();
            derivCls.normalMethod();
 
            Console.ReadLine();
        }
    }
}

In above code, We have declared abstract class abstactClass with one abstract method abstractMethod and one normal method, normalMethod with implementation provided.
We have derivClass which inherits abstractClass, Provide their own implementation for abstract method from abstract class along with we can access normal method declared in abstract class for our derived class.
See in program class's main method we declared variable of derivClass and accessed both the methods.

Now what is the use of abstract class? Let take an example from dot net framework.
In dot net framework, we have DbConnection  abstract class in System.Data.Common namespace.
If you check Definition of  DbConnection  class in dot net framework, you can see below abstract class Definition.

+
using System;
using System.ComponentModel;
using System.Data;
 
namespace System.Data.Common
{
    // Summary:
    //     Represents a connection to a database.
    public abstract class DbConnection : ComponentIDbConnectionIDisposable
    {
        protected DbConnection();
 
        public abstract string ConnectionString { getset; }
 
        public virtual int ConnectionTimeout { get; }
        
        public abstract string Database { get; }
        
        public abstract string DataSource { get; }
        
        protected virtual DbProviderFactory DbProviderFactory { get; }
        
        public abstract string ServerVersion { get; }
        
        public abstract ConnectionState State { get; }
 
        public virtual event StateChangeEventHandler StateChange;
 
        protected abstract DbTransaction BeginDbTransaction(IsolationLevel isolationLevel);
        
        public DbTransaction BeginTransaction();
        
        public DbTransaction BeginTransaction(IsolationLevel isolationLevel);
        
        public abstract void ChangeDatabase(string databaseName);
        
        public abstract void Close();
        
        public DbCommand CreateCommand();
        
        protected abstract DbCommand CreateDbCommand();
        
        public virtual void EnlistTransaction(System.Transactions.Transaction transaction);
       
        public virtual DataTable GetSchema();
        
        public virtual DataTable GetSchema(string collectionName);
        
        public virtual DataTable GetSchema(string collectionName, string[] restrictionValues);
        
        protected virtual void OnStateChange(StateChangeEventArgs stateChange);
        
        public abstract void Open();
    }
}

You can see in above code there are abstract methods/properties as well as normal methods, virtual methods and properties are also declared. The classes which are responsible for connecting to different type of databases are derived from this abstract class. If you check SqlConnection or OleDbConnection class, they both derived from this abstract class. See below class definition of SqlConnection class

+
using Microsoft.SqlServer.Server;
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Runtime.ConstrainedExecution;
using System.Security;
 
namespace System.Data.SqlClient
{
    // Summary:
    //     Represents an open connection to a SQL Server database. This class cannot
    //     be inherited.
    public sealed class SqlConnection : DbConnectionICloneable
    {
       
        public SqlConnection();
        
        public SqlConnection(string connectionString);
 
        public override string ConnectionString { getset; }
        
        public override int ConnectionTimeout { get; }
        
        public override string Database { get; }
        
        public override string DataSource { get; }
        protected override DbProviderFactory DbProviderFactory { get; }
       
        public bool FireInfoMessageEventOnUserErrors { getset; }
        
        public int PacketSize { get; }
        
        public override string ServerVersion { get; }
        
        public override ConnectionState State { get; }
        
        public bool StatisticsEnabled { getset; }

        public string WorkstationId { get; }
 
        public event SqlInfoMessageEventHandler InfoMessage;
 
        protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel);
        
        public SqlTransaction BeginTransaction();
        
        public SqlTransaction BeginTransaction(IsolationLevel iso);
       
        public SqlTransaction BeginTransaction(string transactionName);
        
        public SqlTransaction BeginTransaction(IsolationLevel iso, string transactionName);
        
        public override void ChangeDatabase(string database);
       
        public static void ChangePassword(string connectionString, string newPassword);
        
        public static void ClearAllPools();
       
        public static void ClearPool(SqlConnection connection);
        
        public override void Close();
        
        public SqlCommand CreateCommand();
        protected override DbCommand CreateDbCommand();
        protected override void Dispose(bool disposing);
        
        public void EnlistDistributedTransaction(System.EnterpriseServices.ITransaction transaction);
        
        public override void EnlistTransaction(System.Transactions.Transaction transaction);
        
        public override DataTable GetSchema();
       
        public override DataTable GetSchema(string collectionName);
        
        public override DataTable GetSchema(string collectionName, string[] restrictionValues);
        
        public override void Open();
        
        public void ResetStatistics();
        
        public IDictionary RetrieveStatistics();
    }
}

If you see both classes, we have ConnectionString Property declared as abstract in DbConnection
class. Now each class have different ConnectionString for connecting to respective database. e.g. for above
SqlConnection class, we have ConnectionString defined for connecting to Sql Database. Same like for OleDbConnection class, we have different ConnectionString defined for connecting to other databases. So by using abstract class and deriving class from it, forces derived classes to use common naming convention across various classes but provide flexibility to give their own implementation. This ensures Code Maintainability.
Another importance of Abstract class is, We can declare and implement methods/properties in abstract class that are common to all derived classes. e.g. in our DbConnection class, we have method BeginTransaction() which handles transaction across all databases. Transaction method across all databases is same. So this method is common to all other derived classes. No need to write separate method for each derived class.

No comments :