Introduction
Everyone, I'm sure, who has allowed for more than a passing
perusal of .NET must be excited at the power of its Framework. Those with
a pure programming background and earlier knowledge of pre-.NET technologies
have found those to be sorely lacking in the solidity and methodology of a
pure OOP (Object-Oriented Programming) environment and or language.
All newcomers to .NET are faced with a new challenge - adjust
their thinking process in programming and undoing many bad habits they've
acquired when working with a non-OOP environment. Developers with prior ASP/VBScript
experience certainly fell upon these habits simply because it never promoted
such practices. Therefore, when coming to .NET it can be quite challenging
having to rethink or relearn all "programmed" mindsets.
What I will aim at achieving in this article is to get all non-OOP
programmers up to speed with this whole brave new world of thinking when programming.
Making an allowance for terms such as classes, objects,
properties, structs, overloading, inheritance, abstraction, and polymorphism
can seem unapproachable to non-seasoned programmers with insufficient OOP
awareness. Therefore, my intention is to cut to the chase with all these methodologies
and terms, and demonstrate how they all fit together.
Although this article won't be an exhaustive OOP treatise, its
objective nevertheless is to present in a quick and dirty manner C#/VB
Object-Oriented Programming. Moreover, even though this article may
be slightly geared more towards C#, all important VB assessments or similarities
are addressed and demonstrated. By the way, keep in mind C# is very case sensitive.
Incidentally, don't be put off at the length of this article, a lot of it
is simply repeated code examples for both languages.
OOPs
Object Oriented Programming
is the concept of programming with objects.
What are objects? The computer your seeing this on, the paper you may have
printed this on, the printer, your car, TV, etc. are all objects, you get
the idea. Moreover, they contain features as well as other objects within
them as well. Now the great thing about .NET is that it is itself one huge
object-oriented collection. Objects not quite like the ones we'll create and
mention, but of a different kind, i.e. Data Objects, System Objects, String
Objects, etc. However, unless the objects created are used in concert with
other objects they defeat their true nature.
There are two good reasons why you would love programming OOP
objects. One is that you have full control over how anyone would use the object
you created, and two, encapsulation, in other
words your hard earned OOP code is protected and hidden from everyone - systematized
together. No one could modify it or change it, certainly anyone not qualified.
They simply are available for a specific use, and this is key.
Take for example, if you build one great functional object that
does all sorts of math computations, data retrieval and string formatting,
and it's going to be used in your company. By not only compiling it, but also
by virtue of programming it the OOP way, you protect your intellectual property
long after you're gone.
OOP techniques promote the idea of reusability and further allow
for all involved in knowing the object's uses, concealing the inner working
of your code from inexperienced programmers, simply permitting the object
its task alone.
In the old ASP/VB days, you would've had to have created a compiled
COM component to realize some of the aforementioned
benefits and any gains in performance. However, with .NET this isn't the case
since the entire framework is compiled, every page and so forth. Thus building
objects in .NET is that and so much more. You have the ability to create new
super objects, modularize common code and
design lightly coded, cleanly laid out pages. The bottom line is a strong,
clean architecture from which stems greater productivity and fewer headaches.
No wonder .NET's code-behind, template driven environment espouses all this!
In Object-Oriented Programming, you are dealing with objects.
Now, when you embark on any new project you obviously hope in doing the least
work possible. Consequently, upon any modifications to your project you don't
have to make those changes a thousand times!
Aside from the examples we'll explore how these techniques can
apply to everything you are going to work with. Take data access for instance,
why not create a data-accessing object with properties whose parameters are
the connection string and the query string? In turn, this could be placed
throughout your application thus avoiding maintenance headaches and promoting
a much cleaner design.
Namespaces
.NET furthers the scope of OOP by compartmentalizing objects
within namespaces, as an excellent means of categorizing and personalizing
common and related fields, classes,
structs or interfaces as a collection,
as well as other namespaces known as nested
namespaces! When including namespaces in an application, C# uses the "using"
keyword to do that, whereas VB specifies "Imports."
This is what facilitates and advances proper reusability and
OOP practices. Devoid of this, you would have little structure. Creating a
library of common class filled namespaces makes for a well-created application,
always having modular components ready for use.
|
[C#]
namespace JimsEstate {
public class House { ... }
public class Car { ... }
public class Garage { ... }
}
[VB]
Namespace JimsEstate
' Classes and other types of members go here
End Namespace
|
Here we have the namespace JimsEstate that contains a House,
Car and Garage. All are neatly categorized together, and confusion in minimized,
thus namespaces. Naming namespaces could easily extend beyond this. JimsEstate
could be named JimsEstate.Land.NewYork.LongIsland, if you so choose. That's
cool!
At any rate, we'll now look at one of the component types within
- classes.
A Class in Objects
Simply put, a class is a created
object. In more detail, a class
is a reference type (that which stores some
type of information) that encapsulates (hides
or encloses) and or modularizes (making for
flexible, varied use) any amount of methods (functions
or subroutines), fields, variables or properties or constructors (object
creating function) that classifies data and performs some kind of functionality.
Thus, the focal point of OOP is to classify all common functionality and members
within a main class that when utilized or instanced
in your application, it becomes an object.
Object creation is achieved by using the new
keyword in your code, as we'll see.
The examples we'll mostly focus will revolve around the House
class and its key traits/characteristics. Now if we had a house class
and it contained its pertinent house characteristics (fields
or variables) it would look something like this. So go ahead and place
your preferred language code section in a text file. Next save it as
House.cs if using C# or House.vb for
VB. This is your source file that you'll
compile in the next section.
|
[C#]
public class House {
// Its members
// This is known
as initializing a field - see the "Quick Structs" section
further down
// public string HseColor = "gray";
public string HseBuilder;
public string HseSize;
public string HseColor;
public string Summary() {
return HseBuilder + " is
building a new house that's " + HseSize
+ " and is painting it " + HseColor;
}
}
[VB]
Public Class House
Public HseBuilder As String
Public HseSize As String
Public HseColor As String
Public Function Summary() As String
Return HseBuilder &"
is building a new house that's " & HseSize
&" and is painting it " & HseColor
End Function
End Class
|
The bits of information we include above in our House blueprint
is who the builder is, the house's size and its color. Further enhanced by
a summary entailing overall what's included and taking place within our House
class.
Therefore, even though this is one template describing one house,
it could easily represent and be utilized for any number of houses since each
of its public properties values or characteristics
may be different each newly created instance of it. In the example above,
our diverse information is contained in our public
variables or fields that hold what we pass to them in memory. Our variables
and method string declaration is known as a data
type. In VB the As keyword specifies
the data type, in C# the data type precedes the variable name and or method.
The term for using a class, as many times as you wish, each
time with different characteristics, is called instantiation
or creating an object for use. So the first time the house class is instantiated
and assigned it can hold the properties for example, HseSize of "Big"
and an HseColor of "Red", and when re-instanced could hold some
other very different information. So out of our one House class, we've build
two houses all with different characteristics; one class - many uses.
Variables as we've seen have
the ability to hold one set value. Class properties
unlike their close relatives variables, as
we'll examined a little further down, extend the functionality and pretense
by allowing you to carry out conditional checking within them preventing any
faulty values passed in. Therefore, you can do much, in turn furthering the
nature and objective of OOP, as we'll soon examine in the next section.
All we've discussed still needs to be demonstrated real world.
Therefore, we'll now build two houses, each with its own particular qualities.
So here goes:
A House Building Class
Now that you've already created your house.cs source file, next
run the command below to invoke .NET compiler to compile your source file
into a DLL we can use, and is located in our root bin folder.
|
[C#]
csc /t:library /out:c:\inetpub\wwwroot\bin\house.dll
house.cs /optimize
[VB]
vbc /t:library /out:c:\inetpub\wwwroot\bin\house.dll
house.vb /optimize
|
Additionally, all code examples throughout are to be compiled
in this manner, dependent of course of the language of your choice.
Now that we have the "materials" for our house let's
build two houses out of one blueprint if I may. Place the preferred language
code below in a .aspx page named House.aspx,
then run it in your browser.
[C#]
<%@ Page Language="C#"%>
<html>
<head>
<title>Building a House</title>
</head>
<script language="C#" runat="server">
protected void Page_Load(Object Source, EventArgs E) {
// Build Jim's house
House JimsHouse = new House();
JimsHouse.HseBuilder = "Jim";
JimsHouse.HseSize = "huge";
JimsHouse.HseColor = "blue.";
Response.Write (JimsHouse.Summary() + "<BR><BR>");
// Clear the object
JimsHouse = null;
// Build Lumi's house
House LumisHouse = new House();
LumisHouse.HseBuilder = "Lumi";
LumisHouse.HseSize = "simply breathtaking";
LumisHouse.HseColor = "however she wants.";
Response.Write (LumisHouse.Summary());
// Clear the object
LumisHouse = null;
}
</script>
</body>
</html>
[VB]
<%@ Page Language="VB"%>
<script language="VB" runat="server">
Protected Sub Page_Load(Source As Object, E As EventArgs)
' Build Jim's house
Dim JimsHouse As New House()
With JimsHouse 'VB syntax shortcut
.HseBuilder = "Jim"
.HseSize = "huge"
.HseColor = "blue."
End With
Response.Write (JimsHouse.Summary())
' Clear the object
JimsHouse = Nothing
End Sub
</script>
|
And our results should look like this:
| Jim is building a new house that's huge and is painting it blue.
Lumi is building a new house that's simply breathtaking and is painting
it however she wants.
|
To embark on OOP reusability, by using the new
keyword we declared and instantiated
our object (bring our class to use) - this is know as early
binding (the prefered method of dealing with objects). Thus, we write
in C# - House JimsHouse = new House() or Dim JimsHouse As New House() in VB;
observe C#'s case preference. Essentially, what we're saying here is create
a "new House()" object called JimsHouse, that calls our classes
default constructor - new
House() (which is the same as House.new()),
with no parameters, whereas custom constructors
utilize parameters.
Then we define or pass its characteristics to the fields
in our class. Once we do all this we next call our summary method to return
to us our stats. After this, as in every example throughout this article,
you must always clear your objects. C# uses the object
= null; statement, whereas in VB it's object
= Nothing to do this.
So that's it more or less, the basis of object creation and
OOP. Not too shabby... but wait.
Let's Up The Variables' Property Value A
Bit
Huh? Sorry, I always try for clever wordplay :-) The usage of
variables as seen is direct and to the point. But what if we had someone trying
to build a house with color's that simply won't do? Well aside from our field
assignment, I'll now demonstrate fields kicked
up a notch - these being properties that allow
you to perform conditional testing to prevent any faulty or unwanted values
from being passed in.
Within our properties you deal with two accessors
- Get and Set,
that work in a read-write fashion. Get retrieves
and references any calls from within, for which Set
assigns our value when called.
In addition, our summary method now employs our properties as
an alternative to our simple variables.
| [C#]
public class House {
//Exposed variables
public string ShowSize;
public string HseBuilder;
public string HseColor;
//Private properties
private string ShowBuilder {
get {return HseBuilder;}
set {HseBuilder = value;}
}
private string ShowColor{
get {
if (HseColor == "red"){
return HseColor + ". But I'll change it to white.";
}else{
return HseColor;
}
set {HseColor = value;}
}
public string Summary() {
return ShowBuilder + " is
building a new house that's " + ShowSize
+ " and is painting it " + ShowColor;
}
}
[VB]
Public Class House
Public ShowSize As string
Public HseBuilder As string
Public HseColor As String
Private Property ShowBuilder As String
Get
return HseBuilder
End Get
Set
HseBuilder = value
End Set
End Property
Private Property ShowColor As String
Get
If (HseColor = "red") Then
Return HseColor & ". But I'll change it to white."
Else
Return HseColor
End If
End Get
Set
HseColor = value
End Set
End Property
Public Function Summary() As String
Return ShowBuilder & "
is building a new house that's " & ShowSize
& " and is painting it " & ShowColor
End Function
End Class |
And in our .aspx page we can add, and by now you should've gotten
the VB conversion idea as well, the code below:
House MyOtherHouse = new House();
MyOtherHouse.HseBuilder = "Dude";
MyOtherHouse.ShowSize = "looks ok";
MyOtherHouse.HseColor = "red";
Response.Write (MyOtherHouse.Summary());
|
So after all's said and done our results will look like this:
|
Dude's building a new house that's looks OK and is painting it red.
But I'll change it to white.
|
The first and last values of our summary method are utilized
from our private properties ShowBuilder(), and ShowColor()
that incorporates our conditional statement checking that if someone tries
to paint our house red, we'll change that to white. The second one is simply
from our plain variable - ShowSize. Therefore,
we can clearly observe how properties are
like super sized variables. Both are accessed the same way, but properties
have a little more power over what you permit to take place.
Notice how we use words like public
or private in front of our methods, properties
or variables? These are what are generally known as access
modifiers. In our object, recall how our HseBuilder, HseSize, and HseColor
variables are public. With access modifiers we implicitly determine for our
object's user what members they will be allowed
to be modify or gain access to, their scope
in other words.
In our example, the properties that retrieve these assigned
public variables and analyze their content
are private, and accessible to the class itself
and cannot be accessed externally. The true nature of OOP insists on such,
that the whole intent is defined by their proper usage, determining their
external access allowances.
There are five allowed modifiers or accessibility levels in
C# and they consist of:
- public - Full access is allowed to this
- private - Accessible from within the calls
that contains it
- internal - Can only be accessed from the
current DLL or assembly. Friend in VB.
- protected - Like private above, and could
be access in a class derived from the one it's in
- protected internal - Can only be accessed
from any derived class, itself and like internal - the current DLL it resides
in. In VB this would be Protected Friend.
Note: Any time you don't specify any modifiers
to a variable, it will default to private.
Likewise, on any properties or methods, its
modifiers default to public.
Moreover, as far are modifiers are concerned, others exist,
for both variable fields and methods, that won't be looked into here, like
extern, volatile, sealed, NotInheritable or
NotOverridable, etc. In light of the article's objective, .NET's exhaustive
documentation would suffice better in clarifying any terms not delved into
here. Still, upon reading this guide, any other OOP terms and their supposed
uses won't be nearly as challenging to figure out as they may have once been.
Quick Structs
Let's now examine C# structs,
or structures as they're referred to in VB.
Simply stated, these little bitties act and look just like classes, and utilize
all the same kinds of modifiers and elements a class
would. You could just think of them as light weight, scaled down classes.
Nevertheless, two caveats though: One, is that they are best
suited for smaller data value types under
16 bytes - structures like numbers crunching. Thus, they are used with memory
efficiency in mind, as their memory allocation is superior to classes. Two,
another key difference in comparison to classes is that they cannot inherit
from any other classes as any typical class could, nor could they be a base
class either. However, they could implement interfaces though. Also, unlike
classes, structs could be instantiated without the new
keyword is you so choose. Hmm...
Additionally, classes when instantiated within .NET allocate
memory on the heap or .NET's reserved memory space. Whereas structs yield
more efficiency when instantiated due to allocation on the stack. Furthermore,
it should be noted that passing parameters within structs are done so by value.
A brief word on field initialization and access. Typically,
a class field could easily be initialized or preset with a value, as shown:
public class House {
public string HseColor = "gray";
//This is known as initializing a field
} |
However, this won't work for structs unless the fields are static.
Whenever we initialize any fields, they're typically known as instance fields/data,
whereas the opposite holds true for fields declared with the static
keyword. The main difference between the two is that a static field is accessible
anywhere in your application without having to instantiate the class containing
it. In VB the equivalent keyword is Shared.
[C#]
public class House or
struct House {
public static HseColor = "gray";
//This is known as initializing a field
}
[VB]
Public Class House or
Structure House
Public Shared HseColor As
String = "gray"
End Structure |
Accessing this kind of field is as simple as:
|
Response.Write (House.HseColor)
|
Now getting back to our structs. In the House class as shown
earlier, changing the "public class House" to "struct House"
make's it now a struct like so:
|
[C#]
struct House {
// ... Rest of code here
}
[VB]
Structure House
' ... Rest of code here
End Structure
|
Structs are instantiated in your page in the same manner as
classes as we've shown. Again, although our listed struct example works fine
as is, keep in mind all the aforementioned limitations and key purposes when
implementing them in your programs.
Here we'll now quickly overview classes and other members they
could contain and or independently behave as:
- Fields or Variables - A value that is associated
with and within an object or class. Declared with modifiers such as public,
private, static, shared, const (constants), etc.
- Constants - A consistent, unchanged value
that is associated with an object or class.
- Properties - Advanced and more adaptable
fields, with get and set accessors.
- Methods - Encapsulated code performing an
action or storing some logic.
- Classes - A reference
type that stores and encloses methods (functions
or subroutines), fields, variables or properties, constructors, and even other
classes that organize data and perform some kind of functionality.
- Structs - Light weight, scaled down memory
efficient classes.
- Constructors - creates an instance of a
class whenever the object is created.
- Destructors - destroys the instance of a
class.
- Interfaces - Are a set of specifying arrangements
with certain characteristics, that when implemented or inherited in a class
must abide by. They could contain all mentioned here.
- Events - Are sent notifying something of
actions going to or taking place.
- Delegates - Are useful for events and for
passing one method or function to another as a parameter. Similar to function
pointers in C++.
- Indexers - these allow you to index classes
like you would arrays.
- Enums - Also known as enumerations,
these are a series of constant and related
values.
Sorry, if I blew your mind with all these terms. It's good to
have an idea what they do although you may never use all of them. Nevertheless,
I thought a good passing insight was in order.
I won't go into mind numbing detail on every single aspect of
OOP, nor everything listed above, as this is not the article's intent. Rather
the aim is, as aforementioned, to present the reader with a quick and dirty
introduction and synopsis on all more important commonly used principles of
OOP, so you can get a good overall idea and grasp on it.
As you now have a decent grasp on the methodology of objects,
classes, and properties, we can now press on and claim our .NET inheritance.
:-)
Inheritance
Inheritance in OOP is simply taking features from one object
and implementing them in another one, like having a new super-duper object,
with your new class being a subclass of, and inheriting from, the derived
base or main class. Inheritance plays a vital role when attempting to create
new custom controls in .NET. For example when creating a Composite
Control (made up of multiple server controls) it is formed through inheriting
all the features found within the base Class Control.
In any event, let's work with our house class in creating a
new class called Location, that will simply show us where our house is located.
I'll inherit all the features of our derived house class and then obtain the
same output in addition to our location from the code below:
|
[C#]
public class House {
// Code same as above
}
public class Location : House {
public string ShwLocation;
private string Loc {
get {return ShwLocation;}
set {ShwLocation = value;}
}
public string ShowStats(){
return base.Summary() + "
It is located in " + Loc;
}
}
[VB]
'Inheritance syntax in VB
Public Class Location : Inherits House
or alternatively
Public Class Location
Inherits House
' Rest of code here as above
End Class
|
OK let's examine what's taking place. We've created a new class
Location, right in the same .cs source file
with our House class, that inherited all the features (fields, methods, etc.)
from our derived base
class House. We set up our public ShwLocation
field and our private Loc property
to get and set our value. Next we create a new method ShowStats() and within
it use base.Summary() to pull in the Summary()
method's results from our inherited main class, and thus our new ShowStats()
method's combined results as seen below.
And our .NET page now has this:
Location oHouse = new Location();
oHouse.HseBuilder = "Peter";
oHouse.HseSize = "looks OK";
oHouse.HseColor = "red";
oHouse.ShwLocation = "New York";
Response.Write (oHouse.ShowStats());
|
Here we create a new Location object and we use fields that
are not in our Location object, but are in our House object! We've inherited
all its features and added the ShwLocation
only, and this is one not found in our base class but our new subclass.
That's inheritance.
Your result:
|
Peter built a new house that's looks OK and is painting it red. But
I'll change it to white. It is located in New
York.
|
Pretty nice. Now wouldn't it be even nicer still if we could
inherit from multiple classes? Sure would, but only C++ gives you that luxury
as of late. However, interfaces, as we'll look over a little later, are just
that luxury to make up for it.
Lest we become Abstracted
Huh? I thought I'd be innovative. Well, let's now look into
another type of class, although nothing new to VB - Abstract
classes. These are classes that act like generic, nonfunctional templates,
on the surface similar to Interfaces, for
more specialized classes that could contain both non-abstract and abstract
methods or properties, etc., intended for a new, more robust class. Their
selling point is their ability to remain silent, minimally predisposed and
standing by ready to be redefined and implemented once inherited, and further
help in pinpointing any runtime compilation or implementation errors.
Both abstract classes and interfaces cannot be instantiated.
As we'll examine later, interfaces are contracts
for other classes behavior with no set functionality. Although similar in
concept, abstract classes however can contain abstract functionality (methods,
etc.), as well as typical non-abstract methods.
Therefore, creating one take's place when you use the keyword
abstract as you declare the class. When inheriting
an abstract class in a regular or non-abstract class, you need to override
all methods or properties before implementing, unless they are not abstract
members. When implementing non-abstract members inherited from an abstract
class in a non-abstract class you need to use the keyword Shadows
in VB and new in C#. This behavior is known
as method hiding.
Abstract classes are more useful when multiple versions of a
component are required and for more larger sets of code, as opposed to an
interface with its purpose aimed at smaller, unrelated bits of functionality.
Remember the Class Vs Struct comparison? Kind of like that. Moreover, abstract
classes could also inherit from non-abstract classes and even interfaces!
This is a basis for polymorphism as we'll later examine. However
not quite in this context, since we're not altering it base form to another
form.
Below we create an abstract House class with abstract members.
Upon creating a new non-abstract class we inherit our abstract class and implement
its features by overriding them, like so:
| [C#]
public abstract class House
{
public abstract string ShowColor();
public abstract string ShowSize();
//Non-Abstract method
public string Whatever(){
return "Anything";
}
}
public class HouseStats : House
{
public override string ShowColor()
{
return "blue";
}
public override string ShowSize()
{
return "small";
}
//Method Hiding
public new string Whatever(){
return "New Value";
}
}
[VB]
Public MustInherit Class House
MustOverride Function ShowColor()
'Non-Abstract Method
Public Function Whatever() As String
Return "Anything"
End Function
End Class
Public Class HouseStats : Inherits
House
Overrides Function ShowColor()
Return "blue"
End Function
Public Shadows Function Whatever()
As String
Return "New Value"
End Function
End Class |
As you can tell, the C# keyword abstract
translated to MustInherit in VB, in turn defining
these types of classes and non-instantiable base classes.
Consequently, because of its design, abstract classes, and interfaces
as we'll later examine, work well avoiding run-time bugs associated with derived
classes, due to their nature in being overridden when used.
Parameters
The concept of passing parameters
is nothing new to OOP, and certainly not an incredibly difficult concept to
grasp, since the same techniques were used when programming ASP/VB parameterized
subroutines and functions. And what exactly are parameters? Values.
Shortly, as we explore Overloading,
you'll simultaneously gain knowledge of this concept as well, if you already
didn't.
Method Overloading
Method Overloading or Overloading
is the means of re-implementing a method with the same name numerous times,
providing its signatures (or number of parameter
and or parameter reference types) are different.
To demonstrate, we'll now overload our ShowStats()
method (taken from the Inheritance section code example) two different ways.
Right after the default ShowStats method you can create overloaded methods,
ready for implementation depending on your purpose like so:
public string ShowStats(string
StartTxt){
return base.Summary() + " - " + StartTxt
+ " it is located in " + Loc;
}
public object ShowStats(string
StartTxt, string EndTxt){
return base.Summary() + " - " + StartTxt
+ " it is located in " + Loc + " - " + EndTxt;
}
|
Our default ShowStats() method
as noted before is the standard non-overloaded method. Above however, we've
added an additional two methods, both overloading our default method. The
first one a string method, accepts only one
parameter StartTxt, thus its signature
distinguishes it from its predecessor. The second pushes further by being
an object method with two
parameters, StartTxt and EndTxt. Both retrieving Loc from before as
well.
And in our .aspx page we implement it, in addition to the way
we did before, like this:
//Overloaded method 1
Response.Write (oHouse.ShowStats("I think")
+ "<BR><BR>");
//Overloaded method 2
Response.Write (oHouse.ShowStats("I'm
sure","That's cool!")
+ "<BR><BR>");
|
Same name, different signatures thus overloading, and our results:
|
[Overloaded method 1]
Peter built a new house that's looks OK and is painting it red. But
I'll change it to white. - I think it
is located in New York
[Overloaded method 2]
Peter built a new house that's looks OK and is painting it red. But
I'll change it to white. - I'm sure
it is located in New York - That's cool!
|
Interfaces
Back in our section on abstract classes we dealt with interfaces
in comparison. We briefly explained that they look like classes but they don't
get instantiated in your page as would a typical class. Reason for this is
that they are used or inherited by other classes for a particular functionality
as a contract. In other words, they provide
specs or behaviors for other classes as to their use or redefinition rather
than their direct implementation. Incidentally, interfaces are C#'s answer
to C++'s multiple inheritance.
Now to create an interface we'd declare
an interface with the interface keyword and
specify the interface name. Good naming convention suggests a capital "I"
before the interface name to avoid any confusion and to confirm a naming structure.
Key points:
- As a rule, interfaces are always, by default public,
as are their members.
- Interfaces could contain the following members: methods, properties and
events
- All the members within an interfaces, whether a method or field, cannot
themselves contain anything, they would need to be empty without any body
text.
- Interfaces themselves could even inherit other interfaces, and without having
to implementing all its methods, unlike classes, which have to!
- Both classes as well as structs could inherit multiple interfaces.
In addition, whatever methods or properties the interfaces contain,
they would all have to be implemented upon
inheriting them in your new class. Still if you prefer you can conditionally
check if an actual interface is valid from within by using the is
operator.
Furthermore, implementing and redefining methods and properties
of an interface can be done two ways: implicitly,
that we do, via our publicly and or virtually declared members, or explicitly,
which are referenced directly via the interface name.
Below, the C# examples are no different than before, however,
the VB implementation requires some attention. Multiple Inheritance as we've
touched upon in light of interfaces, can be accomplished this way:
|
[C#]
interface IAllStats
{
int ShowSquareFeet { get; } //Interface
property
void ShowOwner(); //Interface method
}
interface IAllStats2 {
string OwnerName { get; set;
} //Interface property
void ShowLocation(); //Interface method
}
public class UseBothInterfaces : IAllStats, IAllStats2
//Multiple Inheritance feature of Interfaces
{
// Field for interface property
private string _OwnerName;
// Property implementation
public int ShowSquareFeet {
get { return 3600; } //Read
only value
}
public string OwnerName { //Getter and Setter
property
get { return _OwnerName;
}
set { _OwnerName = value; }
}
public void ShowOwner() { OwnerName = "Pete"; } //
ShowOwner() method implemented, assigning OwnerName
public void ShowLocation() { } // ShowLocation()
method implemented
public object ShowStats(){
//ShowOwner(); // Method called - overrides
property
return OwnerName + " owns
a house that's " + ShowSquareFeet
+ " square feet";
}
}
[VB]
Interface IAllStats
ReadOnly Property ShowSquareFeet()
As Integer 'This property is only read only
Function ShowOwner() As String
End Interface
Interface IAllStats2
Property OwnerName() As String
Function ShowLocation() As String
End Interface
Public Class UseBothInterfaces : Implements
IAllStats, IAllStats2 'Multiple Inheritance
feature of Interfaces
Private _OwnerName As String
Public ReadOnly Property ShowSquareFeet
As Integer Implements IAllStats.ShowSquareFeet
Get
Return 3600 'Read only value
End Get
End Property
Property OwnerName As String Implements
IAllStats2.OwnerName 'Getter and Setter
property
Get
Return _OwnerName
End Get
Set
_OwnerName = value
End Set
End Property
Public Function ShowOwner() As String
Implements IAllStats.ShowOwner
OwnerName = "Pete"
End Function
Public Function ShowLocation() As
String Implements IAllStats2.ShowLocation
' ShowLocation() method implemented
End Function
Public Function ShowStats() As Object
' ShowOwner() '
Method called - overrides property - See results
below
Return OwnerName & " owns
a house that's " & ShowSquareFeet
& " square feet"
End Function
End Class
|
Implementing this is as easy as this:
|
[C#]
UseBothInterfaces StatsInter = new UseBothInterfaces();
StatsInter.OwnerName = "Jim";
Response.Write (StatsInter.ShowStats());
[VB]
Dim StatsInter As UseBothInterfaces = New UseBothInterfaces()
StatsInter.OwnerName = "Jim"
Response.Write (StatsInter.ShowStats())
|
OK, now what took place? Well, we created two interfaces that
include both method and properties
(both a standard string property and readonly
integer property). Next we set up our class that inherits multiple
interfaces, and we then begin defining their members from our two interface
templates.
In our above .aspx page code, we instance
our class UseBothInterfaces(), and proceed to
assign our object's OwnerName() method a value,
and then write out our results. Our ShowStats()
method is set up to do two things. Call, thus implement, the ShowOwner()
method along with its code (which overwrites Jim
with Pete), and or return to us the OwnerName
that was set from our page's object instantiation, alongside our ShowSquareFeet()
method's measurements that were internally already assigned.
Therefore, working with interfaces offers us the ability and
has demonstrated how we could inherit and implement multiple interfaces in
a class, assign and retrieve property values, implement methods and return
results that can be accomplished either internally or externally through our
web page from our two contracts. In our example we decided to implement both
interfaces, and all define all their members.
|
[Results without ShowOwner() method implemented]
Jim owns a house that's 3600
square feet
[Results with ShowOwner() method implemented]
Pete owns a house that's 3600
square feet
|
Another point to note is that our VB code in comparison to C#
requires the Implements keyword referencing
the implemented interface and method. Again upon implementing an interface,
you must implement all the members of that
interface, unlike abstract classes that do not support multiple inheritance,
but are allowed to choose what members you wish to implement, as long as you
specify to the contrary.
Quick observation: Creating an instance of the class inheriting
multiple interfaces is demonstrate above in our BothInterfaces() method. Now
notice that we create an instance and we could reference any class that implements
any interface. Moreover, interfaces due to their insistent complete implemenation
schema could go a long way in preventing runtime bugs.
As we'll explore polymorphism,
you'll discover instantiation of a different kind, that applies to interfaces
as well.
Finally Polymorphism
Polymorphism is really pretty easy to understand. First off,
it is derived from two Greek words "Poly" meaning many and "Morphism"
means forms or shapes. In OOP this is taken to mean how one object is used
as if it's another different object altogether. Key factors for polymorphism
to take place are that the methods involved are overridable. Furthermore,
upon polymorphism via inheritance, you are able to construct a uniquely new
object based on a commonly derived method.
Any polymorphic methods in C# are declared with the keyword
virtual or abstract, and the method overriding
this specifies override. In VB you're dealing
with Inheritable/Overridable methods. Contrary to overloading,
overriding must include the identical features, including all the signatures
(number of parameters) as the derived base class method.
|
[C#]
public class House
{
public virtual string GetStatistics()
{
return ("My House is spacious");
}
}
public class GuestHouse : House
{
public override string GetStatistics()
{
return ("My House now a Guesthouse is roomy");
}
}
public class Garage : House
{
public override string GetStatistics()
{
return ("My House now a Garage is wide");
}
}
[VB]
MustInherit Public Class House
Public MustOverride Function GetStatistics()
As String
Return ("My House is spacious")
End Function
End Class
Public Class Guesthouse : Inherits House
Public Overrides Function GetStatistics()
As String
Return ("My House now a Guesthouse is roomy")
End Function
End Class
Public Class Garage : Inherits House
Public Overrides Function GetStatistics()
As String
Return ("My House now a Garage is wide")
End Function
End Class
|
What was accomplished here through abstract polymorphism is
that we overrode and modified the GetStatistics's
return value. The other concept of Polymorphism - Inheritance-Based Polymorphism,
work much along the same lines.
Our code to instantiate them is:
|
[C#]
House myHouse = new House();
House myGuestHse = new Guesthouse();
House myGarage = new Garage();
Response.Write(myHouse.GetStatistics() + "<BR>");
Response.Write(myGuestHse.GetStatistics() + "<BR>");
Response.Write(myGarage.GetStatistics());
[VB]
Dim myHouse As House = New House()
Dim myGuestHouse As House = New Guesthouse()
Dim myGarage As House = New Garage()
Response.Write(myHouse.GetStatistics() & "<BR>")
Response.Write(myGuestHouse.GetStatistics() & "<BR>")
Response.Write(myGarage.GetStatistics() & "<BR>")
|
And our results are:
|
My House is spacious
My House now a Guesthouse is roomy
My House now a Garage is wide
|
So even though I declared my variables as a House, through polymorphism
my House object takes on a different type and gets transformed into myGuestHouse
and even myGarage! Think of the possibilities.
Phew! Not too bad. Well take heart that you have learned a great
deal of OOP concepts and now should find it less cumbersome.
Conclusion
In conclusion, beyond all we've touched upon, OOP can be quite
extensive in its depth and conceptual methodologies. There is far more that
can be learned, including everything from sealed and non-inheritable classes
to delegates and events and so forth, to say the least. The intricacy of OOP
unquestionably extends far beyond what was described here.
Still, the foundation we've set forth I hope is an excellent
start and overview of OOP for you. There are hundreds of great resources online
that would allow you a deeper look into the illimitable complexities and structures
of OOP. Yet, learning all these concepts is best accomplished like most things
in development, having something to make use of them in and performing real-world
work.
In close, my objective here was to introduce a direct and to
the point outline of OOP that should now have given you a firm place to stand
on from which you now could plan your next move on the road to object-oriented
application development. </>
Until next time, Happy .NETing!
Dimitrios Markatos