Abstract Interfaces
Abstract Interfaces
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 Interface?
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:
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.
using System;
namespace AbstractsANDInterfaces
{
///
/// Summary description for Employee.
///
//properties
public abstract String ID
{
get;
set;
}
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";
}
}
}
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;
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;
}
String Update();
String Add();
String Delete();
String Search();
String CalculateWage();
}
}
Inherited Objects
using System;
namespace AbstractsANDInterfaces
{
///
/// Summary description for Emp_Fulltime.
///
5
//Abstract class therefore no
//properties or fields here!
public Emp_Fulltime()
{
}
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();
}
Emp_Fulltime2
using System;
namespace AbstractsANDInterfaces
{
///
/// Summary description for Emp_fulltime2.
///
public Emp_fulltime2()
{
//
// TODO: Add constructor logic here
//
7
}
public String ID
{
get
{
return id;
}
set
{
id = value;
}
}
8
public String Search()
{
return "Fulltime Employee " +
fname + " searched.";
}
IEmployee emp;
9
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
Employee emp;
//no casting is requird!
emp = new Emp_Fulltime();
emp.ID = "2244";
emp.FirstName= "Maria" ;
emp.LastName = "Robinlius" ;
MessageBox.Show(emp.Add().ToString());
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
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
.WindowState =
you'll get a pop-up list of the supported constants, and can simply pick “wdWindowStateMaximize” from the
list.
.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.
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
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.
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
Now the signature of the delegate must match the signature of method
above.
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.
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);
C# Implementation
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.
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.
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();
}
}
}
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();
}
}
}
Another Example
17
// ClassA
class A
{
public void M()
{
Console.WriteLine("A.M() being called");
}
// Class B
class B : A
{
public new void M()
{
Console.WriteLine("B.M() being called");
}
say
A a = new B();
a.M();
a.N();
18