Vous êtes sur la page 1sur 18

Introduction

In this article along with the demo project I will discuss Interfaces versus Abstract
classes. The concept of Abstract classes and Interfaces is a bit confusing for
beginners of Object Oriented programming. Therefore, I am trying to discuss the
theoretical aspects of both the concepts and compare their usage. And finally I will
demonstrate how to use them with C#.

Background

An Abstract class without any implementation just looks like an Interface; however
there are lot of differences than similarities between an Abstract class and an
Interface. Let's explain both concepts and compare their similarities and differences.

What is an Abstract class?

An abstract class is a special kind of class that cannot be instantiated. So the


question is why we need a class that cannot be instantiated? An abstract class is only
to be sub-classed (inherited from). In other words, it only allows other classes to
inherit from it but cannot be instantiated. The advantage is that it enforces certain
hierarchies for all the subclasses. In simple words, it is a kind of contract that forces
all the subclasses to carry on the same hierarchies or standards.

What is an Interface?

An interface is not a class. It is an entity that is defined by the word Interface. An


interface has no implementation; it only has the signature or in other words, just the
definition of the methods without the body. As one of the similarities to Abstract
class, it is a contract that is used to define hierarchies for all subclasses or it defines
specific set of methods and their arguments. The main difference between them is
that a class can implement more than one interface but can only inherit from one
abstract class. Since C# doesn’t support multiple inheritance, interfaces are used to
implement multiple inheritance.

Both together

When we create an interface, we are basically creating a set of methods without any
implementation that must be overridden by the implemented classes. The advantage
is that it provides a way for a class to be a part of two classes: one inheritance
hierarchy and one from the interface.

When we create an abstract class, we are creating a base class that might have one
or more completed methods but at least one or more methods are left uncompleted
and declared abstract. If all the methods of an abstract class are uncompleted then
it is the same as an interface but with the restriction that it cannot make a class
inherit from it. The purpose of an abstract class is to provide a base class definition
for how a set of derived classes will work and then allow the programmers to fill the
implementation in the derived classes.

1
There are some similarities and differences between an interface and an abstract
class that I have arranged in a table for easier comparison:

Feature Interface Abstract class

Multiple inheritance A class may inherit A class may inherit only


several interfaces. one abstract class.

Default implementation An interface cannot An abstract class can


provide any code, just provide complete, default
the signature. code and/or just the
details that have to be
overridden.

Constants Only Static final Both instance and static


constants. constants are possible.

Core VS Peripheral Interfaces are used to An abstract class defines


define the peripheral the core identity of a class
abilities of a class. In and there it is used for
other words both Human objects of the same type.
and Vehicle can inherit
from a IMovable
interface.

Homogeneity If the various If the various


implementations only implementations are of
share method signatures the same kind and use
then it is better to use common behaviour or
Interface. status then abstract class
is better to use.

Speed Requires more time to Fast


find the actual method in
the corresponding
classes.

Adding functionality If we add a new method If we add a new method


to an Interface then we to an abstract class then
have to track down all the we have the option of
implementations of the providing default
interface and define implementation and
implementation for the therefore all the existing
new method. code might work properly.

Using the code

Let me explain the code to make it a bit easier. There is an Employee abstract class
and an IEmployee interface. Within the Abstract class and the Interface entity I am
commenting on the differences between the artifacts.

2
I am testing both the Abstract class and the Interface by implementing objects from
them. From the Employee abstract class, we have inherited one object:
Emp_Fulltime. Similarly from IEmployee we have inherited one object:
Emp_Fulltime2.

In the test code under the GUI, I am creating instances of both Emp_Fulltime and
Emp_Fulltime2 and then setting their attributes and finally calling the
calculateWage method of the objects.

Abstract Class Employee

using System;

namespace AbstractsANDInterfaces
{
///
/// Summary description for Employee.
///

public abstract class Employee


{
//we can have fields and properties
//in the Abstract class
protected String id;
protected String lname;
protected String fname;

//properties
public abstract String ID
{
get;
set;
}

public abstract String FirstName


{
get;
set;
}

public abstract String LastName


{
get;
set;
}
//completed methods
public String Update()
{
return "Employee " + id + " " +
lname + " " + fname +
" updated";

3
}
//completed methods
public String Add()
{
return "Employee " + id + " "+
lname + " " + fname +
" added";
}
//completed methods
public String Delete()
{
return "Employee " + id + " "+
lname + " " + fname +
" deleted";
}
//completed methods
public String Search()
{
return "Employee " + id + " "+
lname + " " + fname +
" found";
}

//abstract method that is different


//from Fulltime and Contractor
//therefore i keep it uncompleted and
//let each implementation
//complete it the way they calculate the wage.
public abstract String CalculateWage();

}
}

Interface Employee

using System;

namespace AbstractsANDInterfaces
{
/// <summary>
/// Summary description for IEmployee.
/// </summary>
public interface IEmployee
{
//cannot have fields. uncommenting
//will raise error!
// protected String id;
// protected String lname;
// protected String fname;

//just signature of the properties

4
//and methods.
//setting a rule or contract to be
//followed by implementations.
String ID
{
get;
set;
}

String FirstName
{
get;
set;
}

String LastName
{
get;
set;
}

// cannot have implementation


// cannot have modifiers public
// etc all are assumed public
// cannot have virtual

String Update();

String Add();

String Delete();

String Search();

String CalculateWage();
}
}

Inherited Objects

using System;

namespace AbstractsANDInterfaces
{
///
/// Summary description for Emp_Fulltime.
///

//Inheriting from the Abstract class


public class Emp_Fulltime : Employee
{
//uses all the properties of the

5
//Abstract class therefore no
//properties or fields here!

public Emp_Fulltime()
{
}

public override String ID


{
get
{
return id;
}
set
{
id = value;
}
}

public override String FirstName


{
get
{
return fname;
}
set
{
fname = value;
}
}

public override String LastName


{
get
{
return lname;
}
set
{
lname = value;
}
}

//common methods that are


//implemented in the abstract class
public new String Add()
{
return base.Add();
}
//common methods that are implemented
//in the abstract class
public new String Delete()

6
{
return base.Delete();
}
//common methods that are implemented
//in the abstract class
public new String Search()
{
return base.Search();
}
//common methods that are implemented
//in the abstract class
public new String Update()
{
return base.Update();
}

//abstract method that is different


//from Fulltime and Contractor
//therefore I override it here.
public override String CalculateWage()
{
return "Full time employee " +
base.fname + " is calculated " +
"using the Abstract class...";
}
}
}

Emp_Fulltime2

using System;

namespace AbstractsANDInterfaces
{
///
/// Summary description for Emp_fulltime2.
///

//Implementing the interface


public class Emp_fulltime2 : IEmployee
{
//All the properties and
//fields are defined here!
protected String id;
protected String lname;
protected String fname;

public Emp_fulltime2()
{
//
// TODO: Add constructor logic here
//

7
}

public String ID
{
get
{
return id;
}
set
{
id = value;
}
}

public String FirstName


{
get
{
return fname;
}
set
{
fname = value;
}
}

public String LastName


{
get
{
return lname;
}
set
{
lname = value;
}
}

//all the manipulations including Add,Delete,


//Search, Update, Calculate are done
//within the object as there are not
//implementation in the Interface entity.
public String Add()
{
return "Fulltime Employee " +
fname + " added.";
}

public String Delete()


{
return "Fulltime Employee " +
fname + " deleted.";
}

8
public String Search()
{
return "Fulltime Employee " +
fname + " searched.";
}

public String Update()


{
return "Fulltime Employee " +
fname + " updated.";
}

//if you change to Calculatewage().


//Just small 'w' it will raise
//error as in interface
//it is CalculateWage() with capital 'W'.
public String CalculateWage()
{
return "Full time employee " +
fname + " caluculated using " +
"Interface.";
}
}
}

Code for testing

//This is the sub that tests both


//implementations using Interface and Abstract

private void InterfaceExample_Click(object sender,


System.EventArgs e)
{
try
{

IEmployee emp;

Emp_fulltime2 emp1 = new Emp_fulltime2();


//has to be casted because of the interface!
emp = (IEmployee) emp1;
emp.ID = "2234";
emp.FirstName= "Rahman" ;
emp.LastName = "Mahmoodi" ;
//call add method od the object
MessageBox.Show(emp.Add().ToString());

//call the CalculateWage method


MessageBox.Show(emp.CalculateWage().ToString());

9
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}

private void cmdAbstractExample_Click(object sender,


System.EventArgs e)
{

Employee emp;
//no casting is requird!
emp = new Emp_Fulltime();

emp.ID = "2244";
emp.FirstName= "Maria" ;
emp.LastName = "Robinlius" ;
MessageBox.Show(emp.Add().ToString());

//call the CalculateWage method


MessageBox.Show(emp.CalculateWage().ToString());

Early binding:: Properties and method can be identified by compile time.


Example: dim rs as recordset

Late binnding: Properties and method can be identified by Run time.


Example: dim obj as classname
set obj=new classname

Early Binding & Late Binding concepts in .NET can be easily understood if we take the example of using
COM in .NET.
Early Binding means compiler must have prior knowledge about COM, its functions and properties i.e. at
compile time. So that Visual Studio can use Intellisense to show you the methods and properties supported
by COM while coding. What one has to do is simply add reference of COM through 'Add Reference' from
'Solution Explorer'. After adding reference, you can use your COM just like .NET namespace that is by
instancing your COM class as normal C# class instantiation.
Late Binding means compiler doesn't have any prior knowledge about COM's methods and properties and it
is delayed until runtime. Actually program learns the addresses of methods and properties at execution time
only i.e. when those methods and properties are invoked. Late bound code typically refers client objects
through generic data types like 'object' and relies heavily on runtime to dynamically locate method
addresses. We do late binding in C# through reflection. Reflection is a way to determine the type or
information about the classes or interfaces. We don't need to create RCW for the COM component in late
binding as we did in early binding. We use 'GetTypeFromProgID' to get the type object for the COM object's
type information than we’ll use 'CreateInstance' to instantiate the COM object of appropriate type

Advantages of Early Binding

Your code will run considerably faster, because it can all be compiled up front. With late binding, the code
relating to an application you declared as an object has to, in effect, be compiled as it runs.
Because your code can all be compiled up front, debugging is far easier – select Debug + Compile, and the
compiler will be able to spot syntax errors which would have been missed had you used late binding.
You have full access in your project to intellisense (type a keyword and a dot to get a popup list of properties

10
and methods supported by that keyword, select one to insert it; type a keyword and press F1 to launch the
Help topic on that keyword).
You have full access to the application's object model via the Object Browser and VBA Help.
You have access to the application's built-in constants. For instance, if you are automating Word from Excel,
you can use:
Dim objWord As Word.Application
Set objWord = New Word.Application

With objWord
.Visible = True
.Activate
.WindowState = wdWindowStateMaximize
.Documents.Open ("c:\temp\temp.doc")
End With

Furthermore, when you type

.WindowState =

you'll get a pop-up list of the supported constants, and can simply pick “wdWindowStateMaximize” from the
list.

If you used late binding, you would need to use:

.WindowState = 1

.. and you would need to know (by looking it up in Word's Object Browser) that the value of the constant
“wdWindowStateMaximize” happens to be 1.

All this makes programming using early binding immeasurably easier than using late binding.

Advantages of Late Binding


The main advantage is that code which uses late binding is more certain to be version-independent

If you set a reference in a Word 97 project to “Microsoft Excel 8.0 Object Library”, then the project will run
OK on a machine which has Office 2000 installed. Word 2000 changes the reference on the fly to the
“Microsoft Excel 9.0 Object Library”.

But as they famously say, YMMV. Problems have been found in certain circumstances. For instance, if you
run a Word 97 project containing a reference to the Excel 8.0 object library on a machine with Office 2000
installed, it will run OK, but you may get the occasional “cannot open macro storage” error unless you save
the project in Word 2000. If you do save it in Word 2000, the reference will change to the Excel 9.0 object
library. So if you use early binding and support a mixed environment, it may be safest to create separate
Word 97 and Word 2000 versions of your addins, despite the maintenance overhead.

The more references your project contains, the larger the file size and the longer it takes to compile.
Some programming environments don't allow you to create references to another application.
As someone who finds programming difficult at the best of times, I would never dream of using late binding –
why make life harder for yourself than it has to be? But some programming geniuses prefer to use late
binding, because of the peace of mind it gives them regarding version independence – or maybe some of
them just enjoy the challenge! <g> But you pays your money and makes your choice ...
To those unfortunate souls using programming environments in which you have to use late binding, all I can
say is: Look on the bright side – you could have ended up as an Assembly language programmer ...

11
Execution Flow of ASPX Pages by IIS:

The execution of ASP .Net pages are not singly handled by the Internet Information Server or in
short hand form IIS. It is taken care by the worker process aspnet_wp.exe. Whenever the IIS
receives a request from a web browser or a client requesting for a page, it delegates the job to
the aspnet_wp.exe process, which takes care of the subsequent jobs and finally returns the
HTML page back to the IIS.

When ASP .Net is installed, installation process creates an association for .aspx files with the
aspnet_isapi.dll files. When the IIS receives a request from the clients or web browsers for an
aspx page, the IIS web server hands this request over to the aspnet_isapi.dll, which in turn
instantiates the aspnet_wp.exe job. This aspnet_wp.exe finalizes any unfinished jobs like run time
compilation etc., as explained above and then executes the asp .net application in a new
application domain. Finally the output page is generated and returned back to the web server,
which in-turn sends the file over to the client

Delegates in C#

Imagine that you need your program to call a method, but you can't know what that method
will be until run-time. Perhaps it's a sort method, such as a bubble sort, merge sort, or quick
sort. What if your algorithm needs a mathematical function, but the exact algorithm can't be
determined until specific data is analyzed? Sometimes, generic GUI events and controls need
to provide notification mechanisms for their events, but only the developer knows which
callbacks are appropriate for a given implementation. All of these situations are practical
applications and reasons for using delegates.

With delegates, you can reference methods and build algorithms that work, regardless of what
those methods are. If you're familiar with C++, you might recognize this as being the same as
function pointers. However, the difference with C# is that delegates are object-oriented and
type safe.

Delegate Signatures

A delegate type is specified by a distinct signature, which includes a unique identifier,


parameter list, and return type. The following code shows how to declare a delegate:

public delegate double UnitConversion(double from);

The example above contains a full definition of a delegate. Just like any other namespace
element, delegates are declared as either public or internal, with a default of internal
accessibility if the modifier is not specified. Delegates may also be declared as nested types,
with accessibility modifiers allowable for their containing class or struct.

The C# keyword delegate identifies this as a delegate declaration. The return type of this
delegate is double, its identifier is "UnitConversion," and it has a single parameter of type
double. Looking at both the delegate identifier and parameter identifier, you can get an idea of
the purpose of this delegate, which is to serve as a definition of methods that perform a
conversion of units from one type to another.

12
A delegate declaration is appended with a semi-colon. Delegates do not have implementation.
Instead, they are a skeleton defining the proper signature of delegate handler methods to
which they may refer. The handler methods contain implementation that is executed when its
referring delegate is invoked.

Delegates

In this article we will deal with Delegates in C#. I purposely tried to keep this article
very simple so that people could understand the basics of delegates. After this I will
extends its boundaries towards Events in DotNet.

Delegates in C# are objects which points towards a function which matches its
signature. Delegates are reference type used to encapsulate a method with a specific
signature. In C++ you accomplish this task by having pointer to a function. Unlike
pointers delegates are type-safe. A delegate in C# allows you to pass a methods of
class to objects of other classes. You can pass a method Print in class A class B by
wrapping it in a delegate and class B is able to access the method of class A.

Functionality of Delegates can be accomplished in four steps.

1. In order to create a delegate its signature must match the signature of the
object you are trying to encapsulate in a delegate. For e.g we consider a
simple function Print(). Its signature is like

2. Public void print()


3. {
4. Console.Writeline("Hello")
5. }

Now the signature of the delegate must match the signature of method
above.

Public void Mydelegate();

Look the declaration of delegate it does not return anything nor it takes
anything as argument. This doesn't mean that we cannot declare delegate
which can take argument and return arguments.

A delegate which takes an argument and return string.

public string MySecondDelegate(int number);

furthermore delegate can encapsulate Instance Method as well as static


methods which match its signature.

6. In this step define all the methods which has the same signature as the
delegate defined.
7. In this step create the delegate object and pass the method as a parameter to
delegate.

13
8. Mydelegate l_objMyDelegate=new Mydelegate(print);

the method print encapsulated

9. Now call the encapsulated method using delegate object.

Diagram Explaining the Delegate.

C# Implementation

Code of Button Pentium!:

private void btnPentiumI_Click(object sender, System.EventArgs e)


{
Computer l_objComputer=new Computer();
ComputerType l_objCallComputer=new
ComputerType(l_objComputer.PentiumI);
l_objCallComputer();
}
Code of Button Pentium!!:

private void btnPentiumIISS_Click(object sender, System.EventArgs e)


{
Computer l_objComputer=new Computer();
ComputerType l_objCallComputer=new
ComputerType(l_objComputer.PentiumII);
l_objCallComputer();
}

If you look at the code you will notice that I have created an object of class
Computer and then I also created an object of my Delgate that is ComputerType
and then encapsulate or pass my desired function as its parameter the I just called
the delegate which in return execute the given method.

Code of computer class:

using System;
using System.Windows.Forms;

namespace delegatesprac
{
///

14
/// Summary description for Computer.
///
public class Computer
{
///
/// Method petium! that has the similar
/// signature as Delegate ComputerType
///
public void PentiumI()
{
MessageBox.Show("Configuration: Pentium! 200MMX "+
"2.1 GB HardDrive "+
"32 MB RAM "+
"32X CD-ROM");
}

///
///Method petium!! that has the similar
/// signature as Delegate ComputerType
///
public void PentiumII()
{
MessageBox.Show("Configuration: Pentium!! 350MMX "+
"4.3 GB HardDrive "+
"64 MB RAM "+
"40X CD-ROM");
}
}
///
/// Delegate Computer type
///
public delegate void ComputerType();

}
Description

The above program defines a class Computer it has two methods Pentium! And
Pentium!!. In the same file I defined the delegate that is ComputerType. Its has
similar signature as the function Pentium! And Pentium!!. Now the coding of
buttons Pentium! and Pentium!!. If you look at the code you will notice that I have
created an object of class Computer and then I also created an object of my Delgate
that is ComputerType and then encapsulate or pass my desired function as its
parameter the I just called the delegate which in return execute the given method.

Virtual Functions in C# ---- An Example

15
HI consider this situation
using System;
using System.Collections.Generic;
using System.Text;

namespace @virtual
{
class Base
{
public void Display()
{
Console.WriteLine("I am from base");
}

}
class Derived : Base
{
public void Display()
{
Console.WriteLine("I am from derived");
}
}
class Program
{
static void Main(string[] args)
{
Base b = new Derived();
b.Display();
Console.Read();
}
}
}

The result will be I am from Base


If you want to dispaly the derived class method you can use virtual methods
using System;
using System.Collections.Generic;
using System.Text;

namespace @virtual
{
class Base
{
public virtual void Display()
{
Console.WriteLine("I am from base");
}

}
class Derived : Base
{

16
public override void Display()
{
Console.WriteLine("I am from derived");
}
}
class Program
{
static void Main(string[] args)
{
Base b = new Derived();
b.Display();
Console.Read();
}
}
}

this will give I am from Derived

Another Example

17
// ClassA
class A
{
public void M()
{
Console.WriteLine("A.M() being called");
}

public virtual void N()


{
Console.WriteLine("A.N() being called");
}
}

// Class B
class B : A
{
public new void M()
{
Console.WriteLine("B.M() being called");
}

public override void N()


{
Console.WriteLine("B.N() being called");
}
}

say

A a = new B();

a.M();
a.N();

The results would be

A.M() being called


B.N() being called

18

Vous aimerez peut-être aussi