Вы находитесь на странице: 1из 27

In this article we will discuss key concepts of object orientation with their

practical implementation in C#. We will discuss here basics of OOPS


including Interfaces, Access Modifiers, inheritance, polymorphism etc. his is
my second article on csharp!corner.com.
My first article was "Memory Management in .#$",
you can find this article at http%&&www.c!sharpcorner.com&
'pload(ile&tkagarwal&
MemoryManagementIn#et))*+*,,-,./0+*AM&
MemoryManagementIn#et.asp1
2ey Concepts of 3bject 3rientation
Abstraction
$ncapsulation
4olymorphism
Inheritance.
Abstraction is the ability to generali5e an object as a data type that has a
specific set of characteristics and is able to perform a set of actions.
3bject!oriented languages pro6ide abstraction 6ia classes. Classes define the
properties and methods of an object type.
$1amples%
7ou can create an abstraction of a dog with characteristics, such as
color, height, and weight, and actions such as run and bite. he
characteristics are called properties, and the actions are called
methods.
A 8ecordset object is an abstract representation of a set of data.
Classes are blueprints for 3bject.
3bjects are instance of classes.
C# $1ample of Class%
public class 9raw
:
&& Class code.
;
Object References
When we work with an object we are using a reference to that object. 3n the
other hand, when we are working with simple data types such as Integer, we
are working with the actual 6alue rather than a reference.
When we create a new object using the #ew keyword, we store a reference
to that object in a 6ariable. (or instance%
9raw My9raw < new 9raw=
his code creates a new instance of 9raw. We gain access to this new object
6ia the My9raw 6ariable. his 6ariable holds a reference to the object.
#ow we ha6e a second 6ariable, which also has a reference to that same
object. We can use either 6ariable interchangeably, since they both reference
the e1act same object. he thing we need to remember is that the 6ariable
we ha6e is not the object itself but, rather, is just a reference or pointer to
the object itself.
Early binding means that our code directly interacts with the object, by
directly calling its methods. >ince the compiler knows the object?s data type
ahead of time, it can directly compile code to in6oke the methods on the
object. $arly binding also allows the I9$ to use Intelli>ense to aid our
de6elopment efforts= it allows the compiler to ensure that we are referencing
methods that do e1ist and that we are pro6iding the proper parameter
6alues.
Late binding means that our code interacts with an object dynamically at
run!time. his pro6ides a great deal of fle1ibility since our code literally
doesn?t care what type of object it is interacting with as long as the object
supports the methods we want to call. @ecause the type of the object isn?t
known by the I9$ or compiler, neither Intelli>ense nor compile!time synta1
checking is possible but we get unprecedented fle1ibility in e1change.
If we enable strict type checking by using 3ption >trict 3n at the top of our
code modules, then the I9$ and compiler will enforce early binding beha6ior.
@y default, 3ption >trict is turned off and so we ha6e easy access to the use
of late binding within our code.
Access Modifiers
Access Modifiers are keywords used to specify the declared accessibility of a
member of a type.
Public is 6isible to e6eryone. A public member can be accessed using an
instance of a class, by a class?s internal code, and by any descendants of a
class.
Private is hidden and usable only by the class itself. #o code using a class
instance can access a pri6ate member directly and neither can a descendant
class.
Protected members are similar to pri6ate ones in that they are accessible
only by the containing class. Aowe6er, protected members also may be used
by a descendant class. >o members that are likely to be needed by a
descendant class should be marked protected.

Internal/Friend is public to the entire application but pri6ate to any
outside applications. Internal is useful when you want to allow a class to be
used by other applications but reser6e special functionality for the
application that contains the class. Internal is used by C# and (riend by
B@ .#$.

Protected Internal may be accessed only by a descendant class that?s
contained in the same application as its base class. 7ou use protected
internal in situations where you want to deny access to parts of a class
functionality to any descendant classes found in other applications.
Co!osition of an O"#EC$
We use an interface to get access to an object?s data and beha6ior. he
object?s data and beha6iors are contained within the object, so a client
application can treat the object like a black bo1 accessible only through its
interface. his is a key object!oriented concept called $ncapsulation. he
idea is that any programs that make use of this object won?t ha6e direct
access to the beha6iors or data!but rather those programs must make use of
our object?s interface.
here are three main parts of 3bject%
). Interface
*. Implementation or @eha6ior
+. Member or Instance 6ariables
Interface
he interface is defined as a set of methods C>ub and (unction routinesD,
properties C4roperty routinesD, e6ents, and fields C6ariables or attributesD
that are declared 4ublic in scope.
I!leentation or "e%avior
he code inside of a method is called the implementation. >ometimes it is
also called beha6ior since it is this code that actually makes the object do
useful work.
Client applications can use our object e6en if we change the implementation!
as long as we don?t change the interface. As long as our method name and
its parameter list and return data type remain unchanged, we can change
the implementation all we want.
>o Method >ignature depends on%
Method name
9ata types of parameters
$ither 4arameter is passed @yBal or @y8ef.
8eturn type of method.
It is important to keep in mind that encapsulation is a syntactic tool!it allows
our code to continue to run without change. Aowe6er, it is not semantic!
meaning that, just because our code continues to run, doesn?t mean it
continues to do what we actually wanted it to do.
Meber or Instance &ariables
he third key part of an object is its data, or state. $6ery instance of a class
is absolutely identical in terms of its interface and its implementation!the
only thing that can 6ary at all is the data contained within that particular
object.
Member 6ariables are those declared so that they are a6ailable to all code
within our class. ypically member 6ariables are 4ri6ate in scope!a6ailable
only to the code in our class itself. hey are also sometimes referred to as
instance 6ariables or as attributes. he .#$ (ramework also refers to them
as fields.
We shouldn?t confuse instance 6ariables with properties. A 4roperty is a type
of method that is geared around retrie6ing and setting 6alues, while an
instance 6ariable is a 6ariable within the class that may hold the 6alue
e1posed by a 4roperty.
Interface looks like a class, but has no implementation.
he only thing it contains is definitions of e6ents, inde1ers, methods and&or
properties. he reason interfaces only pro6ide definitions is because they are
inherited by classes and structs, which must pro6ide an implementation for
each interface member defined. >o, what are interfaces good for if they
don?t implement functionalityE hey?re great for putting together plug!n!play
like architectures where components can be interchanged at will. >ince all
interchangeable components implement the same interface, they can be
used without any e1tra programming. he interface forces each component
to e1pose specific public members that will be used in a certain way.
@ecause interfaces must be defined by inheriting classes and structs, they
define a contract. (or instance, if class foo inherits from the I9isposable
interface, it is making a statement that it guarantees it has the 9isposeCD
method, which is the only member of the I9isposable interface. Any code
that wishes to use class foo may check to see if class foo inherits
I9isposable. When the answer is true, then the code knows that it can call
foo.9isposeCD.
9efining an Interface% MyInterface.c
interface IMyInterface
:
6oid MethodoImplementCD=
;
Abo6e listing shows defines an interface named IMyInterface. A common
naming con6ention is to prefi1 all interface names with a capital "I", but this
is not mandatory. his interface has a single method named
MethodoImplementCD. his could ha6e been any type of method declaration
with different parameters and return types. #otice that this method does not
ha6e an implementation Cinstructions between curly braces! :;D, but instead
ends with a semi!colon, "=". his is because the interface only specifies the
signature of methods that an inheriting class or struct must implement.
All the methods of Interface are public by default and no access modifiers
Clike pri6ate, publicD are allowed with any method of Interface.
'sing an Interface% InterfaceImplementer.cs
class InterfaceImplementer % IMyInterface
:
public 6oid MethodoImplementCD
:
Console.WriteFineC"MethodoImplementCD called."D=
;
;
he InterfaceImplementer class in abo6e listing implements the IMyInterface
interface. Indicating that a class inherits an interface is the same as
inheriting a class. In this case, the following synta1 is used%
class InterfaceImplementer % IMyInterface
#ote that this class inherits the IMyInterface interface= it must implement its
all members. While implementing interface methods all those needs to be
declared public only. It does this by implementing the MethodoImplementCD
method. #otice that this method implementation has the e1act same
signature, parameters and method name, as defined in the IMyInterface
interface. Any difference will cause a compiler error. Interfaces may also
inherit other interfaces. (ollowing listing shows how inherited interfaces are
implemented.
Interface Inheritance% InterfaceInheritance.cs
using >ystem=
interface I4arentInterface
:
6oid 4arentInterfaceMethodCD=
;
interface IMyInterface % I4arentInterface
:
6oid MethodoImplementCD=
;
class InterfaceImplementer % IMyInterface
:
public 6oid MethodoImplementCD
:
Console.WriteFineC"MethodoImplementCD called."D=
;
public 6oid 4arentInterfaceMethodCD
:
Console.WriteFineC"4arentInterfaceMethodCD called."D=
;
;
he code in abo6e listing contains two interfaces% IMyInterface and the
interface it inherits, I4arentInterface. When one interface inherits another,
any implementing class or struct must implement e6ery interface member in
the entire inheritance chain. >ince the InterfaceImplementer class in abo6e
listing inherits from IMyInterface, it also inherits I4arentInterface. herefore,
the InterfaceImplementer class must implement the MethodoImplementCD
method specified in the IMyInterface interface and the
4arentInterfaceMethodCD method specified in the I4arentInterface interface.
In summary, you can implement an interface and use it in a class. Interfaces
may also be inherited by other interface. Any class or struct that inherits an
interface must also implement all members in the entire interface
inheritance chain.
In%eritance is the idea that one class, called a subclass, can be based on
another class, called a base class. Inheritance pro6ides a mechanism for
creating hierarchies of objects.
Inheritance is the ability to apply another class?s interface and code to your
own class.
#ormal base classes may be instantiated themsel6es, or inherited. 9eri6ed
classes can inherit base class members marked with protected or greater
access. he deri6ed class is speciali5ed to pro6ide more functionality, in
addition to what its base class pro6ides. Inheriting base class members in
deri6ed class is not mandatory.
Access 'ey(ords
base !G Access the members of the base class.
this !G 8efer to the current object for which a method is called.
he base keyword is used to access members of the base class from within a
deri6ed class%
Call a method on the base class that has been o6erridden by another
method. >pecify which base!class constructor should be called when creating
instances of the deri6ed class. A base class access is permitted only in a
constructor, an instance method, or an instance property accessor.
In following e1ample, both the base class, 4erson, and the deri6ed class,
$mployee, ha6e a method named Hetinfo. @y using the base keyword, it is
possible to call the Hetinfo method on the base class, from within the
deri6ed class.
&& Accessing base class members
using >ystem=
public class 4erson
:
protected string ssn < "///!--!...."=
protected string name < "Iohn F. Malgraine"=
public 6irtual 6oid HetInfoCD
:
Console.WriteFineC"#ame% :,;", nameD=
Console.WriteFineC">>#% :,;", ssnD=
;
;
class $mployee% 4erson
:
public string id < "A@C-.J$(H"=
public o6erride 6oid HetInfoCD
:
&& Calling the base class HetInfo method%
base.HetInfoCD=
Console.WriteFineC"$mployee I9% :,;", idD=
;
;
class estClass
:
public static 6oid MainCD
:
$mployee $ < new $mployeeCD=
$.HetInfoCD=
;
;
3utput
#ame% Iohn F. Malgraine
>>#% ///!--!....
$mployee I9% A@C-.J$(H
@ase class constructors can be called from deri6ed classes. o call a base
class constructor, use the baseCD constructor reference. his is desirable
when it?s necessary to initiali5e a base class appropriately.
Aere?s an e1ample that shows the deri6ed class constructor with an address
parameter%
abstract public class Contact
:
pri6ate string address=
public ContactCstring bKaddressD
:
this.address < bKaddress=
;
;
public class Customer % Contact
:
public CustomerCstring cKaddressD % baseCCKaddressD
:
;
;
In this code, the Customer class does not ha6e an address, so it passes the
parameter to its base class constructor by adding a colon and the base
keyword with the parameter to its declaration. his calls the Contact
constructor with the address parameter, where the address field in Contact is
initiali5ed.
3ne more e1ample which shows how base!class constructor is called when
creating instances of a deri6ed class%
using >ystem=
public class My@ase
:
int num=
public My@aseCD
:
Console.WriteFineC"In My@aseCD"D=
;
public My@aseCint iD
:
num < i=
Console.WriteFineC"in My@aseCint iD"D=
;
public int Het#umCD
:
return num=
;
;
public class My9eri6ed % My@ase
:
static int i < +*=
&& his constructor will call My@ase.My@aseCD
public My9eri6edCint iiD % baseCD
:
;
&& his constructor will call My@ase.My@aseCint iD
public My9eri6edCD % baseCiD
:
;
public static 6oid MainCD
:
My9eri6ed md < new My9eri6edCD= && calls public My9eri6edCD % baseCiD and
&& passes i<+* in base class
My9eri6ed md) < new My9eri6edC)D= && call public My9eri6edCD % baseCiD
;
;
3utput
in My@aseCint iD
in My@aseCD
he following e1ample will not compile. It illustrates the effects of not
including a default constructor in a class definition%
abstract public class Contact
:
pri6ate string address=
public ContactCstring addressD
:
this.address < address=
;
;
public class Customer % Contact
:
public CustomerCstring addressD
:
;
;
In this e1ample, the Customer constructor does not call the base class
constructor. his is ob6iously a bug, since the address field will ne6er be
initiali5ed.
When a class has no e1plicit constructor, the system assigns a default
constructor. he default constructor automatically calls a default or
parameterless base constructor. Aere?s an e1ample of automatic default
constructor generation that would occur for the preceding e1ample%
public CustomerCD % ContactCD
:
;
When a class does not declare any constructors, the code in this e1ample is
automatically generated. he default base class constructor is called
implicitly when no deri6ed class constructors are defined. 3nce a deri6ed
class constructor is defined, whether or not it has parameters, a default
constructor will not be automatically defined, as the preceding code showed.
Calling "ase Class Mebers
9eri6ed classes can access the members of their base class if those
members ha6e protected or greater access. >imply use the member name in
the appropriate conte1t, just as if that member were a part of the deri6ed
class itself. Aere?s an e1ample%
abstract public class Contact
:
pri6ate string address=
pri6ate string city=
pri6ate string state=
pri6ate string 5ip=
public string (ullAddressCD
:
string fullAddress < address L ?Mn? L city L ?,? L state L ? ? L 5ip=
return fullAddress=
;
;
public class Customer % Contact
:
public string Henerate8eportCD
:
string fullAddress < (ullAddressCD=
&& do some other stuff...
return fullAddress=
;
;
In abo6e e1ample, the Henerate8eportCD method of the Customer class calls
the (ullAddressCD method in its base class, Contact. All classes ha6e full
access to their own members without Nualification. Oualification refers to
using a class name with the dot operator to access a class member!
My3bject.>omeMethodCD, for instance. his shows that a deri6ed class can
access its base class members in the same manner as its own.
More ips regarding Inheritance%
A static member cannot be marked as o6erride, 6irtual, or abstract. >o
following is an error%
public static 6irtual 6oid Het>>#CD
7ou can?t call static methods of base class from deri6ed class using
base keyword.
In abo6e e1ample if you declare a static method as follows%
public class 4erson
:
protected string ssn < "///!--!...."=
protected string name < "Iohn F. Malgraine"=
public static 6oid HetInfoCD
:
&& Implementation
;
;
now you can?t call this method using base.HetInfoCD from deri6ed class
instead you ha6e to call 4erson.HetInfoCD from deri6ed class.
Inside >tatic members we can access only static fields, methods etc.
(ollowing e1ample will gi6e error, because we can?t access name in HetInfoCD
because name is not static.
public class 4erson
:
protected string ssn < "///!--!...."=
protected string name < "Iohn F. Malgraine"=
public static 6oid HetInfoCD
:
Console.WriteFineC"#ame% :,;", nameD=
Console.WriteFineC">>#% :,;", ssnD=
;
;
Birtual or abstract members cannot be pri6ate.
If you are not o6erriding a 6irtual method of base class in deri6ed
class, you can?t use base class method by using base keyword in
deri6ed class. Also when you will create an instance of deri6ed class, it
will call deri6ed class method and you will only be able to access base
class method when you will create instance of base class.
7ou can?t decrease access le6el of a method in deri6ed class when you
are o6erriding a base class method in deri6ed class, 6ice 6ersa is
possible.
Means you can make protected method of base class to public in
deri6ed class.
he "this" keyword refers to%
the current instance for which a method is called. >tatic member
functions do not ha6e a this pointer. he this keyword can be used to
access members from within constructors, instance methods, and
instance accessors.
he following are common uses of this%
o Nualify members hidden by similar names, for e1ample%
public $mployeeCstring name, string aliasD
:
this.name < name=
this.alias < alias=
;
In abo6e e1ample, this.name refers to pri6ate 6ariable name in the class. If
we write name < name, then this will refer to argument name of the
constructor $mployee and not to pri6ate 6ariable name in the class. In this
case pri6ate 6ariable name will ne6er be initiali5ed.
o pass an object as a parameter to other methods, for e1ample%
Calca1CthisD=
o declare inde1ers, for e1ample%
public int this Pint paramQ
:
get
:
return arrayPparamQ=
;
set
:
arrayPparamQ < 6alue=
;
;
It is an error to refer to this in a static method, static property accessor, or
6ariable initiali5er of a field declaration.
In this e1ample, this is used to Nualify the $mployee class members, name
and alias, which are hidden by similar names. It is also used to pass an
object to the method Calca1, which belongs to another class.
&& keywordsKthis.cs
&& this e1ample
using >ystem=
public class $mployee
:
public string name=
public string alias=
public decimal salary < +,,,.,,m=
&& Constructor%
public $mployeeCstring name, string aliasD
:
&& 'se this to Nualify the fields, name and alias%
this.name < name=
this.alias < alias=
;
&& 4rinting method%
public 6oid print$mployeeCD
:
Console.WriteFineC"#ame% :,;MnAlias% :);", name, aliasD=
&& 4assing the object to the Calca1 method by using this%
Console.WriteFineC"a1es% :,%C;", a1.Calca1CthisDD=
;
;
public class a1
:
public static decimal Calca1C$mployee $D
:
return C,.,0mRC$.salaryDD=
;
;
public class MainClass
:
public static 6oid MainCD
:
&& Create objects%
$mployee $) < new $mployee C"Iohn M. rainer", "jtrainer"D=
&& 9isplay results%
$).print$mployeeCD=
;
;
3utput
#ame% Iohn M. rainer
Alias% jtrainer
a1es% S*/,.,,
Abstract Classes
Abstract classes are a special type of base classes. In addition to normal
class members, they ha6e abstract class members. hese Abstract class
members are methods and properties that are declared without an
implementation. All classes deri6ed directly from abstract classes must
implement all of these abstract methods and properties.
Abstract classes can ne6er be instantiated. his would be illogical, because
of the members without implementations.>o what good is a class that can?t
be instantiatedE FotsT Abstract classes sit toward the top of a class hierarchy.
hey establish structure and meaning to code. hey make frameworks easier
to build. his is possible because abstract classes ha6e information and
beha6ior common to all deri6ed classes in a framework. ake a look at the
following e1ample%
abstract public class Contact && Abstract Class Contact.
:
protected string name=
public ContactCD
:
&& statements...
;
public abstract 6oid generate8eportCD=
abstract public string #ame
:
get=
set=
;
;
Contact, is an abstract class. Contact has two abstract members, and it has
an abstract method named generate8eportCD. his method is declared with
the abstract modifier in front of the method declaration. It has no
implementation Cno bracesD and is terminated with a semicolon. he #ame
property is also declared abstract. he accessors of properties are
terminated with semicolons.
public class Customer % Contact && Customer Inherits Abstract Class Contact.
:
string gender=
decimal income=
int number3fBisits=
public CustomerCD
:
&& statements
;
public o6erride 6oid generate8eportCD
:
&& uniNue report
;
public o6erride string #ame
:
get
:
number3fBisitsLL=
return name=
;
set
:
name < 6alue=
number3fBisits < ,=
;
;
;
public class >ite3wner % Contact
:
int siteAits=
string my>ite=
public >ite3wnerCD
:
&& statements
;
public o6erride 6oid generate8eportCD
:
&& uniNue report
;
public o6erride string #ame
:
get
:
siteAitsLL=
return name=
;
set
:
name < 6alue=
siteAits < ,=
;
;
;
he abstract base class Contact has two deri6ed classes, Customer and
>ite3wner. @oth of these deri6ed classes implement the abstract members of
the Contact class. he generate8eportCD method in each deri6ed class has an
o6erride modifier in its declaration. Fikewise, the #ame declaration contains
an o6erride modifier in both Customer and >ite3wner.
C# reNuires e1plicit declaration of intent when o6erriding methods. his
feature promotes safe code by a6oiding the accidental o6erriding of base
class methods, which is what actually does happen in other languages.
Fea6ing out the o6erride modifier generates an error. >imilarly, adding a new
modifier also generates an error. Abstract methods must be o6erridden and
cannot be hidden, which the new modifier or the lack of a modifier would be
trying to do.
he most famous of all abstract classes is the 3bject class. It may be
referred to as object or 3bject, but it?s still the same class. 3bject is the
base class for all other classes in C#. It?s also the default base class when a
base class is not specified. he following class declarations produce the same
e1act results%
abstract public class Contact % 3bject
:
&& class members
;
abstract public class Contact
:
&& class members
;
3bject is implicitly included as a base class if it is not already declared.
@esides pro6iding the abstract glue to hold together the C# class framework,
object includes built!in functionality, some of which is useful for deri6ed
classes to implement.
)ifference bet(een Interface and Abstract Class
Interfaces are closely related to abstract classes that ha6e all members
abstract.
(or an abstract class, at least one method of the class must be an
abstract method that means it may ha6e concrete methods.
(or an interface, all the methods must be abstract
Class that implements an interface much pro6ide concrete
implementation of all the methods definition in an interface or else
must be declare an abstract class
In C#, multiple inheritance is possible only through implementation of
multiple interfaces. Abstract class can only be deri6ed once.
An interface defines a contract and can only contains four entities 6i5
methods, properties, e6ents and inde1es. An interface thus cannot
contain constants, fields, operators, constructors, destructors, static
constructors, or types.
Also an interface cannot contain static members of any kind. he
modifiers abstract, public, protected, internal, pri6ate, 6irtual, o6erride
is disallowed, as they make no sense in this conte1t.
Class members that implement the interface members must be
publicly accessible.
Overriding Suery*
A deri6ed class may o6erride a 6irtual method of the base class with the
keyword o6erride. he following restrictions must be followed.
2eyword o6erride is used in the definition of child class method that is
going to o6erride the base class?s 6irtual method.
he return type must be the same as the 6irtual method ha6e in base
class.
he name of the method should also be same.
he parameter!list must also be same in order, number and type of
parameters.
he accessibility of the o6erriding method should not be more
restricted than that of the accessibility defined with 6irtual method of
the base class. his accessibility either be the same or less restricted.
he 6irtual methods can be sealed in the child or deri6ed classes to
pre6ent further modifications in the implementation of the 6irtual
method in the deri6ed classes, by declaring them as sealed methods.
+iding "ase Class Mebers
>ometimes deri6ed class members ha6e the same name as a corresponding
base class member. In this case, the deri6ed member is said to be "hiding"
the base class member.
When hiding occurs, the deri6ed member is masking the functionality of the
base class member. 'sers of the deri6ed class won?t be able to see the
hidden member= they?ll see only the deri6ed class member. he following
code shows how hiding a base class member works.
abstract public class Contact
:
pri6ate string address=
pri6ate string city=
pri6ate string state=
pri6ate string 5ip=
public string (ullAddressCD
:
string fullAddress <address L ?Mn? Lcity L ?,? L state L ? ? L 5ip=
return fullAddress=
;
;
public class >ite3wner % Contact
:
public string (ullAddressCD
:
string fullAddress=
&& create an address...
return fullAddress=
;
;
In this e1ample, both >ite3wner and its base class, Contact, ha6e a method
named (ullAddressCD. he (ullAddressCD method in the >ite3wner class hides
the (ullAddressCD method in the Contact class. his means that when an
instance of a >ite3wner class is in6oked with a call to the (ullAddressCD
method, it is the >ite3wner class (ullAddressCD method that is called, not the
(ullAddressCD method of the Contact class.
Although a base class member may be hidden, the deri6ed class can still
access it. It does this through the base identifier. >ometimes this is
desirable. It is often useful to take ad6antage of the base class functionality
and then add to it with the deri6ed class code. he ne1t e1ample shows how
to refer to a base class method from the deri6ed class.
abstract public class Contact
:
pri6ate string address=
pri6ate string city=
pri6ate string state=
pri6ate string 5ip=
public string (ullAddressCD
:
string fullAddress <address L ?Mn? Lcity L ?,? L state L ? ? L 5ip=
return fullAddress=
;
;
public class >ite3wner % Contact
:
public string (ullAddressCD
:
string fullAddress < base.(ullAddressCD=
&& do some other stuff...
return fullAddress=
;
;
In this particular e1ample, the (ullAddressCD method of the Contact class is
called from within the (ullAddressCD method of the >ite3wner class. his is
accomplished with a base class reference. his pro6ides another way to
reuse code and add on to it with customi5ed beha6ior.
&ersioning
Bersioning, in the conte1t of inheritance, is a C# mechanism that allows
modification of classes Ccreating new 6ersionsD without accidentally changing
the meaning of the code. Aiding a base class member with the methods
pre6iously described generates a warning message from the compiler. his is
because of the C# 6ersioning policy. It?s designed to eliminate a class of
problems associated with modifications to base classes.
Aere?s the scenario% A de6eloper creates a class that inherits from a third!
party library. (or the purposes of this discussion, we assume that the
Contact class represents the third!party library. Aere?s the e1ample%
public class Contact
:
&& does not include (ullAddressCD method
;
public class >ite3wner % Contact
:
public string (ullAddressCD
:
string fullAddress < my>ite.o>tringCD=
return fullAddress=
;
;
In this e1ample, the (ullAddressCD method does not e1ist in the base class.
here is no problem yet. Fater on, the creators of the third!party library
update their code. 4art of this update includes a new member in a base class
with the e1act same name as the deri6ed class%
public class Contact
:
pri6ate string address=
pri6ate string city=
pri6ate string state=
pri6ate string 5ip=
public string (ullAddressCD
:
string fullAddress <address L ?Mn? Lcity L ?,? L state L ? ? L 5ip=
return fullAddress=
;
;
public class >ite3wner % Contact
:
public string (ullAddressCD
:
string fullAddress < my>ite.o>tringCD=
return fullAddress=
;
;
In this code, the base class method (ullAddressCD contains different
functionality than the deri6ed class method. In other languages, this
scenario would break the code because of implicit polymorphism. Aowe6er,
this does not break any code in C# because when the (ullAddressCD method
is called on >ite3wner, it is still the >ite3wner class method that gets called.
his scenario generates a warning message. 3ne way to eliminate the
warning message is to place a new modifier in front of the deri6ed class
method name, as the following e1ample shows%
using >ystem=
public class Web>ite
:
public string >ite#ame=
public string '8F=
public string 9escription=
public Web>iteCD
:
;
public Web>iteC string str>ite#ame, string str'8F, string str9escription D
:
>ite#ame < str>ite#ame=
'8F < str'8F=
9escription < str9escription=
;
public o6erride string o>tringCD
:
return >ite#ame L ", " L'8F L ", " L9escription=
;
;
public class Contact
:
public string address=
public string city=
public string state=
public string 5ip=
public string (ullAddressCD
:
string fullAddress <address L ?Mn? Lcity L ?,? L state L ? ? L 5ip=
return fullAddress=
;
;
public class >ite3wner % Contact
:
int siteAits=
string name=
Web>ite my>ite=
public >ite3wnerCD
:
my>ite < new Web>iteCD=
siteAits < ,=
;
public >ite3wnerCstring a#ame, Web>ite a>iteD
:
my>ite < new Web>iteCa>ite.>ite#ame,a>ite.'8F,a>ite.9escriptionD=
#ame < a#ame=
;
new public string (ullAddressCD
:
string fullAddress < my>ite.o>tringCD=
return fullAddress=
;
public string #ame
:
get
:
siteAitsLL=
return name=
;
set
:
name < 6alue=
siteAits < ,=
;
;
;
public class est
:
public static 6oid MainCD
:
Web>ite my>ite < new Web>iteC"Fe (inancier","http%&&www.Fe(inancier.com","(ancy
(inancial >ite"D=
>ite3wner an3wner < new >ite3wnerC"Iohn 9oe", my>iteD=
string address=
an3wner.address < ")*+ Fane Fane"=
an3wner.city < ">ome own"=
an3wner.state < "AI"=
an3wner.5ip < "/-.J0"=
address < an3wner.(ullAddressCD= && 9ifferent 8esults
Console.WriteFineC"Address% Mn:,;Mn", addressD=
;
;
Aere?s the output%
Address%
Fe (inancier, http%&&www.Fe(inancier.com, (ancy (inancial >ite
his has the effect of e1plicitly letting the compiler know the de6eloper?s
intent. 4lacing the new modifier in front of the deri6ed class member states
that the de6elopers know there is a base class method with the same name,
and they definitely want to hide that member. his pre6ents breakage of
e1isting code that depends on the implementation of the deri6ed class
member. With C#, the method in the deri6ed class is called when an object
of the deri6ed class type is used. Fikewise, the method in the base class is
called when an object of the @ase class type is called. Another problem this
presents is that the base class may present some desirable new features
that wouldn?t be a6ailable through the deri6ed class.
o use these new features reNuires one of a few different workarounds. 3ne
option would be to rename the deri6ed class member, which would allow
programs to use a base class method through a deri6ed class member. he
drawback to this option would be if there were other classes relying upon the
implementation of the deri6ed class member with the same name. his
scenario will break code and, for this reason, is considered e1tremely bad
form.
Another option is to define a new method in the deri6ed class that called the
base class method. his allows users of the deri6ed class to ha6e the new
functionality of the base class, yet retain their e1isting functionality with the
deri6ed class. While this would work, there are maintainability concerns for
the deri6ed class.
Sealed Classes
>ealed classes are classes that can?t be deri6ed from. o pre6ent other
classes from inheriting from a class, make it a sealed class. here are a
couple good reasons to create sealed classes, including optimi5ation and
security.
>ealing a class a6oids the system o6erhead associated with 6irtual methods.
his allows the compiler to perform certain optimi5ations that are otherwise
una6ailable with normal classes.
Another good reason to seal a class is for security. Inheritance, by its 6ery
nature, dictates a certain amount of protected access to the internals of a
potential base class. >ealing a class does away with the possibility of
corruption by deri6ed classes. A good e1ample of a sealed class is the >tring
class. he following e1ample shows how to create a sealed class%
public sealed class Customer>tats
:
string gender=
decimal income=
int number3fBisits=
public Customer>tatsCD
:
;
;
public class CustomerInfo % Customer>tats && error
:
;
his e1ample generates a compiler error. >ince the Customer>tats class is
sealed, it can?t be inherited by the CustomerInfo class.he Customer>tats
class was meant to be used as an encapsulated object in another class. his
is shown by the declaration of a Customer>tats object in the Customer class.
public class Customer
:
Customer>tats my>tats= && okay
;
Polyor!%is
4olymorphism is reflected in the ability to write one routine that can operate
on objects from more than one class!treating different objects from different
classes in e1actly the same way. (or instance, if both Customer and Bendor
objects ha6e a #ame property, and we can write a routine that calls the
#ame property regardless of whether we?re using a Customer or Bendor
object, then we ha6e polymorphism.
A 6ehicle is a good e1ample of polymorphism. A 6ehicle interface would only
ha6e those properties and methods that all 6ehicles ha6e, a few of which
might include paint color, number of doors, accelerator, and ignition. hese
properties and methods would apply to all types of 6ehicles including cars,
trucks, and semi!trucks.
4olymorphism will not implement code behind the 6ehicle?s properties and
methods. Instead, polymorphism is the implementation of an interface. If
the car, truck, and semitruck all implement the same 6ehicle interface, then
the client code for all three classes can be e1actly the same.
C# gi6es us polymorphism through inheritance. C# pro6ides a keyword
6irtual that is used in the definition of a method to support polymorphism.
Child class are now free to pro6ide their own implementation of this 6irtual
method, that is called o6erriding. he following points are important
regarding 6irtual keyword%!
If the method is not 6irtual, the compiler simply uses the reference type to
in6oke the appropriate method.
If the method is 6irtual, the compiler will generate code to checkup the
reference type at runtime it is actually denoting to, then the appropriate
method is called from the class of the reference type.
When a 6irtual method is called, runtime check Clate method bindingD is
made to identify the object and appropriate method is in6oked, all this is
done at runtime.
In case of non!6irtual methods, this information is a6ailable at compile time,
so no runtime check to identify the object is made, so slightly efficient in the
way non!6irtual methods are called. @ut the beha6ior of 6irtual method is
useful in many ways= the functionality they pro6ide is fair enough to bear
this slight loss of performance.
I!leenting Polyor!%is
he key factor here is the ability to dynamically in6oke methods in a class
based on their type. $ssentially, a program would ha6e a group of objects,
e1amine the type of each one, and e1ecute the appropriate method. Aere?s
an e1ample%
using >ystem=
public class Web>ite
:
public string >ite#ame=
public string '8F=
public string 9escription=
public Web>iteCD
:
;
public Web>iteC string str>ite#ame, string str'8F, string str9escription D
:
>ite#ame < str>ite#ame=
'8F < str'8F=
9escription < str9escription=
;
public o6erride string o>tringCD
:
return >ite#ame L ", " L'8F L ", " L9escription=
;
;
When we inherit abo6e class, we ha6e two choices to in6oke constructor of
the class. >o this is an e1ample of design time polymorphism. Aere at design
time we ha6e to decide which method we need to in6oke while inheriting the
class.
4olymorphism is the capability of a program to carry out dynamic operations
by implementing methods of multiple deri6ed classes through a common
base class reference. Another definition of polymorphism is the ability to
treat different objects the same way. his means that the runtime type of an
object determines its beha6ior rather than the compile!time type of its
reference.
Suery*
It was a long trip, but I tried to e1plain all the basics of 3bject 3rientation in
C# with some practical e1amples. If you are interested to read my pre6ious
article "Memory management in .#$", you can find it at%
http://www.c-
sharpcorner.com/UploadFile/tkagarwal/MemoryManagementInNet11232!"#$32%M/Memor
yManagementInNet.asp&

Вам также может понравиться