Polymorphism & Inheritance in C#

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 50

Polymorphism & Inheritance in C#

Overview

Deriving Classes Implementing Methods Using Sealed Classes Using Interfaces Using Abstract Classes

Implementing Constructors
A constructor is a special type of method that is invoked when you create a new instance of a class. A constructor is used to initialize the members of the class. The name of a constructor is the same as the name of the class that contains it.

The Need of Constructors


A constructor is special member function within the class which is executed when an object of the class is created.

Types of Constructors
The two types of constructors are:
Instance constructors: They are called whenever an instance of a class is created. These constructors are used to initialize the data members of the class. Static constructors: They are used to initialize the static variables of a class. These variables are created using static keyword and they store values that can be shared by all the instances of a class.

Constructors with Parameters


A constructor can be modified to accept the user-supplied values at run time. Objects can be initialized using the default constructor with values hard-coded in the program. But there might be a requirement where the variables need to be initialized with user supplied values.

Implementing Destructors
Destructors are special methods that are used to release the instance of a class from memory. A class can have only one destructor. The purpose of the destructor is to perform the required memory cleanup action. The .NET Framework automatically runs the destructor to destroy objects in the memory.

Declaration of Destructors
A destructor has the same name as its class but is prefixed with a ~ , which is the symbol of tilde. Destructors cannot be inherited or overloaded. Garbage collection is a process that automatically frees the memory of objects that are no more in use. The decision to invoke the destructor is made by a special program of C# known as the garbage collector. The process of garbage collection happens automatically. It ensures that:
Objects get destroyed Only unused objects are destroyed

Declaration of Destructors
C# provides the following methods to release the instance of a class from memory:
Finalize(): It is a special method that is called from the class to which it belongs or from the derived classes. The Finalize() destructor is called after the last reference to an object is released from the memory. Dispose(): This method is called to release a resource, such as a database connection, as soon as the object using such a resource is no longer in use. The IDisposable interface contains the Dispose() method. Therefore, to call the Dispose() method, the class must implement the IDisposable interface.

Identifying the Life Cycle of an Object


Let us understand the life cycle of an object with the help of the following code:
using System; //Life Cycle of an Object namespace Objects { class TestCalculator { TestCalculator() { Console.WriteLine("Constructor Invoked"); }

Identifying the Life Cycle of an Object


~TestCalculator() { Console.WriteLine ("Destructor Invoked"); } public static void Main(string[] args) { Console.WriteLine("Main() Begins"); TestCalculator Calc1 = new TestCalculator();

The destructor of all the object is invoked when the garbage collector is invoked. The Calc1 object has function scope. Therefore, its constructor is executed after the execution of Main() begins.

Identifying the Life Cycle of an Object


~Console.WriteLine("Inner Block Begins "); TestCalculator Calc2 = new TestCalculator(); Console.WriteLine("Inner Block Ends"); } Console.WriteLine("Main() ends");

The Calc2 object has block scope. Therefore, its constructor is executed after the inner block begins.

} } }

Introducing Polymorphism
In Object-Oriented Programming (OOPs), polymorphism allows one interface to be used for multiple functions. Polymorphism reduces the complexity within the functions of a class of a program. Polymorphism can either be static or dynamic.

Static Polymorphism
Static polymorphism refers to an entity, which exists in various forms simultaneously. C# uses two approaches to implement static polymorphism. These are:
Function overloading: This approach allows using the same name for two or more functions. Each redefinition of a function must use different types of parameters, sequence of parameters, or a number of parameters. Operator overloading: This approach allows user-defined types such as structures and classes, to use overloaded operators for easy manipulation of their objects.

Dynamic Polymorphism
In dynamic polymorphism, the decision about function execution is made at run time. Dynamic polymorphism is more useful than static polymorphism as it provides much more flexibility for manipulating the objects. C# uses two approaches to implement dynamic polymorphism:
Abstract classes: Are the special type of base classes that consist of abstract class members. Virtual functions: Are the functions that do not really exist, however, appear to be present in some parts of the program.

Implementing Function Overloading


Function overloading is implemented by defining two or more functions in a class sharing the same name. In function overloading, each definition of a function must differ in its function signature.

Function Signature
The signature of a function is defined by:
The number of parameters The data types of parameters The sequence of the parameters

Constructor Overloading
Constructors can also be parameterized, and therefore, they can be overloaded. Overloaded constructors are commonly used in C# to provide flexibility while creating an object.

Operator Overloading
Operator overloading provides additional capabilities to C# operators when they are applied to user-defined data types. Only the predefined set of C# operators can be overloaded.

Need for Operator Overloading


To use operators with user-defined data types, they need to be overloaded according to a programmers requirement. The following table describes the overload ability of the operators in C#.

Operators +, -, ! , ~, ++ , --

Description These unary operators take one operand and can be overloaded.

+, -, * , /, %

These binary operators take two operands and can be overloaded.

==, !=, <, >, <=, >= &&, ||

The comparison operators can be overloaded. The conditional logical operators cannot be overloaded directly, but they are evaluated using & and | which can be overloaded.

+=, -=, *=, /=, %= =, ., ?:, ->, new, is, sizeof, typeof

The assignment operators cannot be overloaded. These operators cannot be overloaded.

Deriving Classes
Extending Base Classes Accessing Base Class Members Calling Base Class Constructors

Extending Base Classes


Syntax for deriving a class from a base class
Token class Token concrete Derived class Base class { ... } class CommentToken: Token CommentToken { concrete ... Colon } A derived class inherits most elements of its base

class A derived class cannot be more accessible than its base class

class Token { ... class Outside protected string name; { } void Fails(Token t) class CommentToken: Token { { ... ... public string Name( ) t.name { ... Inherited protected members are implicitly protected in the derived class return name; } Methods of a derived class can access only their inherited protected }members } } Protected access modifiers cannot be used in a struct

Accessing Base Class Members

Calling Base Class Constructors


Constructor declarations must use the base keyword

class Token { protected Token(string name) { ... } ... } class CommentToken: Token { A private base class constructor cannot be accessed by a derived class public CommentToken(string name) : base(name) { } Use the base keyword to qualify identifier scope ... }

Implementing Methods

Defining Virtual Methods Working with Virtual Methods Overriding Methods Working with Override Methods Using new to Hide Methods Working with the new Keyword Practice: Implementing Methods Quiz: Spot the Bugs

Defining Virtual Methods


Syntax: Declare as virtual
class Token { ... public int LineNumber( ) { ... } public virtual string Name( ) ... { Virtual methods are polymorphic } }

Working with Virtual Methods


To use virtual methods:
You cannot declare virtual methods as static You cannot declare virtual methods as private

Overriding Methods
Syntax: class Token Use the override keyword { ... public virtual string Name( ) { ... } } class CommentToken: Token { ... public override string Name( ) { ... } }

Working with Override inherited Methods You can only override identical

virtual methods

class Token { ... public int LineNumber( ) { ... } public virtual string Name( ) { ... } } class CommentToken: Token { ... public override int LineNumber( ) { ... } public override string Name( ) { ... } }

You must match an override method with its associated virtual method
You can override an override method You cannot explicitly declare an override method as virtual You cannot declare an override method as static or private

Using new to Hide Methods


Syntax: Use the new keyword to hide a method

class Token { ... public int LineNumber( ) { ... } } class CommentToken: Token { ... new public int LineNumber( ) { ... } }

Working with the new Keyword


class Token { ... Hide both virtual and non-virtual methods public int LineNumber( ) { ... } public virtual string Name( ) { ... } } class CommentToken: Token { ... new public int LineNumber( ) { ... } public override string Name( ) { ... } }

Resolve name clashes in code Hide methods that have identical signatures

class A { public virtual void M() { Console.Write("A"); } } class B: A { public override void M() { Console.Write("B"); } } class C: B { new public virtual void M() { Console.Write("C"); } } class D: C { public override void M() { Console.Write("D"); } static void Main() { D d = new D(); C c = d; B b = c; A a = b; d.M(); c.M(); b.M(); a.M(); } }

Practice: Implementing Methods

Quiz: Spot the Bugs


class Base { public void Alpha( ) { ... } public virtual void Beta( ) { ... } public virtual void Gamma(int i) { ... } public virtual void Delta( ) { ... } private virtual void Epsilon( ) { ... } } class Derived: Base { public override void Alpha( ) { ... } protected override void Beta( ) { ... } public override void Gamma(double d) { ... } public override int Delta( ) { ... } }

Using Sealed Classes You cannot derive from a sealed class

You can use sealed classes for optimizing operations at run time Many .NET Framework classes are sealed: String, StringBuilder, and so on Syntax: Use the sealed keyword
namespace System { public sealed class String { ... } } namespace Mine { class FancyString: String { ... } }

Using Interfaces
Declaring Interfaces Implementing Multiple Interfaces Implementing Interface Methods Implementing Interface Methods Explicitly Quiz: Spot the Bugs

Declaring Interfaces
Syntax: Use the interface keyword to declare methods
Interface names should begin with a capital I

interface IToken { int LineNumber( ); string Name( ); }


No access specifiers No method bodies

IToken interface LineNumber( ) Name( )

ImplementingorMultiple Interfaces A class can implement zero more interfaces


interface IToken { IToken IVisitable string Name( ); interface interface } interface IVisitable { void Accept(IVisitor v); } An interface can extend zero or more interfaces class AToken: be more accessible than its base interfaces Token class can IToken, IVisitable { ... An interface cannot be more accessible than its base interfaces concrete } A class must implement all inherited interface methods

Implementing Interface Methods


The implementing method must be the same as the interface method class Token: IToken, IVisitable Same access The implementing method can be virtual or non{ Same return virtual virtual string Name( ) public Same name
{ ... } public void Accept(IVisitor v) { ... } }

type

Same parameters

class Token: IToken, IVisitable { string IToken.Name( ) { ... } void IVisitable.Accept(IVisitor v) Restrictions of explicit interface method implementation { ... You can only access methods through the interface } You cannot declare methods as virtual } You cannot specify an access modifier

Implementing Interface Methods Use the fully qualified interface method name Explicitly

Quiz: Spot the Bugs


interface IToken { string Name( ); int LineNumber( ) { return 42; } string name; }

class Token { string IToken.Name( ) { ... } static void Main( ) { IToken t = new IToken( ); } }

Using Abstract Classes


Declaring Abstract Classes Using Abstract Classes in a Class Hierarchy Comparing Abstract Classes to Interfaces Implementing Abstract Methods Working with Abstract Methods Quiz: Spot the Bugs

Declaring Abstract Classes


abstract class Token { Use the abstract keyword ... } class Test { static void Main( ) { new Token( ); } }

Token { abstract }
An abstract class cannot be instantiated

Using Abstract Classes in a Class Example 1 Hierarchy

interface IToken { string Name( ); } abstract class Token: IToken { string IToken.Name( ) { ... } ... } class CommentToken: Token { ... } class KeywordToken: Token { ... }

IToken interface

Token { abstract }

Comment Keyword Token Token concrete concrete

Using Abstract Classes in a Class Example 2 Hierarchy (continued)

interface IToken { string Name( ); } abstract class Token { public virtual string Name( ) { ... } ... }

IToken interface

Token { abstract }

Keyword class CommentToken: Token, IToken Comment { ... Token Token } class KeywordToken: Token, IToken concrete concrete { ... }

Comparing Abstract Classes to Interfaces


Similarities
Neither can be instantiated Neither can be sealed

Differences
Interfaces cannot contain any implementation Interfaces cannot declare non-public members Interfaces cannot extend non-interfaces

Implementing Abstract Methods


Syntax: Use the abstract keyword
abstract class Token { public virtual string Name( ) { ... } public abstract int Length( ); } class CommentToken: Token { public override string Name( ) { ... } Only abstract classes can declare abstract methods public override int Length( ) { ... } Abstract methods cannot contain a method body }

Working with Abstract Methods


Abstract methods are virtual Override methods can override abstract methods in further derived classes Abstract methods can override base class methods declared as virtual Abstract methods can override base class methods declared as override

Quiz: Spot the Bugs class First


{ } public abstract void Method( );

abstract class Second { public abstract void Method( ) { } } interface IThird { void Method( ); } abstract class Third: IThird { }

Lab 10.1: Using Inheritance to Implement an Interface

Summary

Deriving Classes Implementing Methods Using Sealed Classes Using Interfaces Using Abstract Classes

You might also like