0% found this document useful (0 votes)
42 views58 pages

Lecture 05, 06 - Inheritance & Polymorphism

Uploaded by

ahihihi.0602
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
42 views58 pages

Lecture 05, 06 - Inheritance & Polymorphism

Uploaded by

ahihihi.0602
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 58

C# 6 and the .NET 4.

6 Framework

Chapter 6, 8 – Understanding
Inheritance and Polymorphism
Outline
• The basic mechanics of inheritance
• The second pillar of OOP: The details of inheritance
• Programming for Containment/Delegation
• The third pillar of OOP: C#’s polymorphic support
• Understanding base class/derived class casting rules
• The master parent class: System.Object
• Abstract class
• Interfaces
The basic mechanics of inheritance
• Code reuse comes in two flavors:
– containment/delegation model (the "has-a"
relationship)
– inheritance (the "is-a" relationship)
• The basic idea behind inheritance
– new classes can be created using existing classes
A simple base class
using System;
namespace BasicInheritance{
// A simple base class.
class Car{
public readonly int maxSpeed;
private int currSpeed;
public Car(int max){
maxSpeed = max;
}
public Car(){
maxSpeed = 55;
}
public int Speed{
get { return currSpeed; }
set{
currSpeed = value;
if (currSpeed > maxSpeed){
currSpeed = maxSpeed;
}
}
}
}
}
A simple base class
using System;

namespace BasicInheritance
{
class MainClass
{
static void Main(string[] args)
{
Console.WriteLine("***** Basic Inheritance *****\n");
// Make a Car object and set max speed.
Car myCar = new Car(80);

// Set the current speed, and print it.


myCar.Speed = 50;
Console.WriteLine("My car is going {0} MPH", myCar.Speed);
Console.ReadLine();
}
}
}
Specifying the Parent Class of an
Existing Class
• Now assume you want to build a new class named MiniVan
– Supports data for a maximum speed, a current speed, and a property
named Speed to allow the object user to modify the object's state
– Minivan “is-a” car too
• The "is-a" relationship (classical inheritance)
– Allows to build new class definitions that extend the existing class
• The base class
– Existing class serves as the basis for the new one
– Defines common data and members for classes that extend it
• The derived class
– Extends the base class
– Could also be called subclass or child classes
Derived class and accessibility
using System;
namespace BasicInheritance
{
//MiniVan derives from the car
public class MiniVan : Car
{
public void TestMethod(){
//can access to the public member of the base class
Speed = 10;
//cannot access to the private member of the base
//currSpeed = 11;//Error
}
}
}
Revisiting Visual Studio Diagram
THE DETAILS OF INHERITANCE
Create EmployeeApp
• We will demonstrate our inheritance in details using
EmployeeApp created in previous lecture

• Manager is an Employee
• SalesPerson is an Employee
• Manager and SalesPerson
inherit all the public members
of Employee
• In addition, they have their own
special properties too.
Employee.cs
using System;
namespace EmployeeApp
{
class Employee
{
// Field data.
private string empName;
// Properties!
public string Name
{
get { return empName; }
set
{
if (value.Length > 15)
Console.WriteLine("Error! Name length exceeds 15 characters!");
else
empName = value;
}
}
public int ID { get; set; }
public float Pay{ get; set; }
public int Age{ get; set; }
public string SSN{ get; }
Employee.cs
//constructors.
public Employee() { }
public Employee(string name, int id, float pay) : this(name, 0, id, pay, "") { }
public Employee(string name, int age, int id, float pay, string ssn)
{
Name = name;
ID = id;
Age = age;
Pay = pay;
SSN = ssn;
}
public void DisplayStats()
{
Console.WriteLine("Name: {0}", Name);
Console.WriteLine("ID: {0}", ID);
Console.WriteLine("Age: {0}", Age);
Console.WriteLine("Pay: {0}", Pay);
Console.WriteLine("SSN: {0}", SSN);
}
// Methods.
public void GiveBonus(float amount)
{
Pay += amount;
}
}
}
Manager.cs
using System;
namespace EmployeeApp
{
class Manager: Employee//A manager is also an Employee
{
//In addition, manager has a special field
public int StockOptions { get; set;}
}
}
SalesPerson.cs
using System;
namespace EmployeeApp
{
class SalesPerson : Employee //Sale person is also an employee
{
// Salespeople need to know their number of sales.
public int SalesNumber { get; set; }

}
}
Program.cs
using System;

namespace EmployeeApp
{
class MainClass
{
// Create a subclass object and access base class functionality.
static void Main(string[] args)
{
Console.WriteLine("***** The Employee Class Hierarchy *****\n");
SalesPerson fred = new SalesPerson();
fred.Age = 31;
fred.Name = "Fred";
fred.SalesNumber = 50;
Console.ReadLine();
}
}
}
Controlling Base Class Creation with
the base Keyword
• To create a Manager, we need to first create
an Employee
– We should use the base keyword for this case
Manager.cs
using System;
namespace EmployeeApp
{
class Manager : Employee//A manager is also an Employee
{
public Manager(string fullName, int age, int empID,float currPay, string ssn, int numbOfOpts)
: base(fullName, age, empID, currPay, ssn) //When creating manager, need to also create an Employee
{
// This property is defined by the Manager class.
StockOptions = numbOfOpts;
}
//This is a default constructor
public Manager(){}
public int StockOptions//In addition, manager has a special field
{
get;
set;
}
}
}
SalesPerson.cs
using System;
namespace EmployeeApp
{
class SalesPerson : Employee //Sale person is also an employee
{
// Salespeople need to know their number of sales.
public int SalesNumber { get; set; }
// As a general rule, all subclasses should explicitly call an appropriate
// base class constructor.
public SalesPerson(string fullName, int age, int empID, float currPay, string ssn, int numbOfSales)
: base(fullName, age, empID, currPay, ssn)
{
// This belongs with us!
SalesNumber = numbOfSales;
}
// Add back the default constructor
public SalesPerson()
{

}
}
}
Keeping Family Secrets: The protected
Keyword
• Public items
– Are directly accessible from anywhere
• Private items
– Can be accessed only by the class that has defined
them
• Protected items
– Can be accessed directly by any descendant
subclass
Adding a Sealed Class
using System; seal keyword doesn’t allow other
namespace EmployeeApp class to inherit from this class
{
sealed class PTSalesPerson : SalesPerson
{
public PTSalesPerson(string fullName, int age, int empID,
float currPay, string ssn, int numbOfSales)
: base(fullName, age, empID, currPay, ssn, numbOfSales)
{
}
// Assume other members here...
}
}
THE THIRD PILLAR OF OOP:
POLYMORPHIC SUPPORT
A case study
using System;

namespace EmployeeApp
{
class MainClass
{
// Create a subclass object and access base class functionality.
static void Main(string[] args)
{
Console.WriteLine("***** The Employee Class Hierarchy *****\n");
// Give each employee a bonus?
Manager chucky = new Manager("Chucky", 50, 92, 100000, "333-23-2322", 9000);
chucky.GiveBonus(300);
chucky.DisplayStats();
Console.WriteLine();
SalesPerson fran = new SalesPerson("Fran", 43, 93, 3000, "932-32-3232", 31);
fran.GiveBonus(200);
fran.DisplayStats();
Console.ReadLine();
}
}
}

So GiveBonus() method operates identically for all subclasses.


Ideally, the bonus of a salesperson or part-time salesperson should take into account the
number of sales, etc.
The virtual and override Keywords
• Polymorphism
– Provides a way for a subclass to define its own version
of a method defined by its base class
– Is done using the process termed method overriding
• In C# we will use virtual and override keywords
– The virtual keyword marks a method that could be
overridden by the subclass
– The override keyword marks a method that is
overriding the same method from the base class
Virtual Method
using System;
namespace EmployeeApp
{
class Employee
{
……
// Methods.
public virtual void DisplayStats()
{
Console.WriteLine("Name: {0}", Name);
Console.WriteLine("ID: {0}", ID);
Console.WriteLine("Age: {0}", Age);
Console.WriteLine("Pay: {0}", Pay);
Console.WriteLine("SSN: {0}", SSN);
}
public virtual void GiveBonus(float amount)
{
Pay += amount;
}
}
}
Override a Method
using System;
namespace EmployeeApp
{
class Manager : Employee//A manager is also an Employee
{
…… We can access to the method from the base
public override void DisplayStats() class using base keyword
{
base.DisplayStats();
Console.WriteLine("Number of Stock Options: {0}", StockOptions);
}
public override void GiveBonus(float amount)
{
base.GiveBonus(amount);
Random r = new Random();
StockOptions += r.Next(500);
}
}
}
Override a Method
using System;
namespace EmployeeApp
{
class SalesPerson : Employee //Sale person is also an employee
{
……
public override void DisplayStats()
{
base.DisplayStats();
Console.WriteLine("Number of Sales: {0}", SalesNumber);
}
public override void GiveBonus(float amount)
{
int salesBonus = 0;
if (SalesNumber >= 0 && SalesNumber <= 100)
salesBonus = 10;
else
{
if (SalesNumber >= 101 && SalesNumber <= 200)
salesBonus = 15;
else
salesBonus = 20;
}
base.GiveBonus(amount * salesBonus);
}
}
}
Override a Method
using System;

namespace EmployeeApp
{
class MainClass
{
// Create a subclass object and access base class functionality.
static void Main(string[] args)
{
Console.WriteLine("***** The Employee Class Hierarchy *****\n");
// A better bonus system!
Manager chucky = new Manager("Chucky", 50, 92, 100000, "333-23-2322", 9000);
chucky.GiveBonus(300);
chucky.DisplayStats();
Console.WriteLine();

SalesPerson fran = new SalesPerson("Fran", 43, 93, 3000, "932-32-3232", 31);


fran.GiveBonus(200);
fran.DisplayStats();
Console.ReadLine();
}
}
}
Sealing Virtual Members
• sealed keyword is used to indicate that
– Derived types cannot override the marked
method
– E.g., to prevent the PTSalesPerson class from
overriding the virtual GiveBonus() method
ABSTRACT CLASSES
Understanding Abstract Classes
• Currently, the Employee base class
– Supply various data members for its descendants
– Supply two virtual methods (GiveBonus() and
DisplayStats()) that may be overridden by a given
descendant
• If we would never like to use any employee object, but
only their subtypes
– The real purpose of the Employee is to define common
members for all subclasses
– You do not intend anyone to create a direct instance of this
class
– In this case, you can make the class abstract
Abstract class
using System;
namespace EmployeeApp
{
abstract class Employee
{
……
}
}

using System;

namespace EmployeeApp
{
class MainClass
{
// Create a subclass object and access base class functionality.
static void Main(string[] args)
{
//This is a compiled time error since we can't create an instance of an abstract class
Employee e = new Employee();
}
}
}
Understanding the abstract class
• When a class has been defined as an abstract base class
– It may define any number of abstract members
• Abstract members can be used
– To define member that does not supply a default
implementation
– Leaving the subclass to provide the implementation for the
member
• Every subclass must either
– Be an abstract class itself or
– Implement all the abstract methods from the base class
• This trait of OOP allows you to
– Build easily extendable and flexible software applications
The shapes hierarchy
Shape.cs
using System;
namespace Shapes
{
// The abstract base class of the hierarchy.
public abstract class Shape Default value (used if you
{
public string PetName { get; set; } don’t input the name)
public Shape(string name = "NoName")
{ PetName = name; }

// A single abstract method.


public abstract void Draw();
}
}
Circle.cs
using System;
namespace Shapes
{
public class Circle : Shape
{
public Circle()
{
}
public Circle(string name) : base(name)
{
}
//You must either override this method or mark this class as abstract
public override void Draw()
{
Console.WriteLine("Drawing the {0} Circle", PetName);
}
}
}
Hexagon.cs
using System;
namespace Shapes
{
public class Hexagon : Shape
{
public Hexagon()
{
}
public Hexagon(string name) : base(name)
{
}
//You must either override this method or mark this class as abstract
public override void Draw()
{
Console.WriteLine("Drawing {0} Hexagon", PetName);
}
}
}
Program.cs
using System;

namespace Shapes
{
class MainClass
{
public static void Main(string[] args)
{
Console.WriteLine("***** Fun with Polymorphism *****\n");

// Make an array of Shape-compatible objects.


Shape[] myShapes = {new Hexagon(), new Circle(), new Hexagon("Mick"),
new Circle("Beth"), new Hexagon("Linda")};

// Loop over each item and interact with the


// polymorphic interface.
foreach (Shape s in myShapes)
{ Example of use to build extendable
s.Draw(); and flexible software applications
}
Console.ReadLine();
}
}
}
Understanding Member Shadowing
• Member shadowing
– A derived class defines a member that is identical
to a member defined in a base class
– The derived class has shadowed the parent's
version
ThreeDCircle.cs
using System;
namespace Shapes
{
class ThreeDCircle : Circle
{ You can also apply the new keyword
// Hide the PetName property above me.
public new string PetName { get; set; } to any member type inherited from
a base class (field, constant, static
// Hide any Draw() implementation above me. member, or property)
public new void Draw()
{
Console.WriteLine("Drawing a 3D Circle");
}
}

}
Program.cs
using System;

namespace Shapes
{
class MainClass
{
public static void Main(string[] args)
{
//This calls the Draw() method of the ThreeDCircle.
ThreeDCircle o = new ThreeDCircle();
o.Draw();
//This calls the Draw() method of the Circle
Shape s1 = new Circle();
s1.Draw();
//This calls the Draw() method of the Circle class
Shape s2 = new ThreeDCircle();
s2.Draw();
Console.ReadLine();
}
}
}
Type casting
• Reference of a base type can point to subtype
object
– Object obj = new Employee();
• Reference of a subtype cannot point to base type
object
– Object obj = new Employee();
– Employee e = obj;//Error
• If you know the object is of a specific subtype you
can cast it specifically
– Object obj = new Employee();
– Employee e = (Employee) obj;//Correct
as keyword
• Type casting may lead to run-time error
– Object e = new Employee();
– Manager m = (Manager) e;//run-time error
• as keyword
– Cast from one type to another
– Returns null (instead of throwing exception)
incase of incompatible type
– Object e = new Employee();
– Manager m = (Manager) e; //returns null
is keyword
• is keyword to determine whether two items
are compatible
using System;
namespace EmployeeApp{
class MainClass{
static void Main(string[] args) {
Employee e1 = new Manager();
Employee e2 = new SalesPerson();
CheckEmployee(e1);
CheckEmployee(e2);
}
static void CheckEmployee(Employee e){
if(e is SalesPerson){
Console.WriteLine("Your sale number: " + ((SalesPerson)e).SalesNumber);
}
if(e is Manager){
Console.WriteLine("Your stock options: " + ((Manager)e).StockOptions);
}
}
}
}
The Master Parent Class:
System.Object
• Every type ultimately derives from a base class
named System.Object that defines
– a set of common members for every type in the
framework
– A class that does not explicitly define its parent,
the compiler automatically derives your type from
Object
INTERFACE TYPES
Understanding Interface Types
• It is a named set of abstract members
• I.e., interface expresses a behavior that a given
class or structure may choose to support (extend)
• A class or structure can support as many
interfaces as necessary
• E.g., to work with SQL, .NET provides set of
classes (SqlConnection, OleDbConnection, etc)
– But all of these need to implement IDbConnection
– To work with different DBMSs in a consistent way
Interface Types vs. Abstract Classes
• Abstract class
– It may define any number of abstract members
– It is also free to define any number of constructors, field data,
nonabstract members (with implementation), and so on
• Interface
– It contains only member declarations (definitions, not
implementations)
• Abstract class has one major limitation
– Only derived types support the members defined by the abstract class
• In larger software systems
– It is common to develop multiple class hierarchies that have no
common parent
– You have no way to configure types in different hierarchies to support
the same polymorphic interface using abstract class
Defining Custom Interfaces
Interfaces
• It is defined with interface keyword
• Its members never specify an access modifier
– They are all abstract and public implicitly
• It does not contain implementations of members
• It does not have data fields
• It can specify property prototypes
• It does not have constructors
• It can contain event and indexer (study later)
Implementing an Interface
IPointy Interface
using System;
namespace Shapes
{
public interface IPointy
{
int Points{get;}
}
}
Update Hexagon.cs
using System;
namespace Shapes
{
public class Hexagon : Shape, IPointy
{
public Hexagon()
{
}
public Hexagon(string name) : base(name)
{
}
//You must either override this method or mark this class as abstract
public override void Draw()
{
Console.WriteLine("Drawing {0} Hexagon", PetName);
}
public int Points
{
get
{
return 6;
}
}
}
}
Add Triangle.cs
using System;
namespace Shapes
{
public class Triangle : Shape, IPointy
{
public Triangle()
{
}
public Triangle(string name): base(name)
{}
public override void Draw()
{
Console.WriteLine("Drawing {0} the Triangle.", PetName);
}
public int Points{
get{
return 3;
}
}
}
}
Calling interface member
using System;

namespace Shapes
{
class MainClass
{
public static void Main(string[] args)
{
IPointy iPointy;
//Reference of inerface can point to object of its subtype
iPointy = new Hexagon();
Console.WriteLine("Hexagon points: {0}", iPointy.Points);
Console.ReadLine();
}
}
}
Multiple Inheritance with Interface
Types
• An interface can extend multiple base
interfaces
– To design some powerful and flexible abstractions
Multiple Inheritance with Interface
Types
// Multiple inheritance for interface types is a-okay.
interface IDrawable
{
void Draw();
}

interface IPrintable
{
void Print();
void Draw(); // <-- Note possible name clash here!
}

// Multiple interface inheritance. OK!


interface IShape : IDrawable, IPrintable
{
int GetNumberOfSides();
}
Summary
• The basic mechanics of inheritance
• Revisiting Visual Studio class diagrams
• The second pillar of OOP: The details of inheritance
• Programming for Containment/Delegation
• The third pillar of OOP: C#’s polymorphic support
• Understanding base class/derived class casting rules
• The master parent class: System.Object
• Abstract class
• Interfaces
References
Troelsen, A. & Japikse, P., 2015. C# 6 and the
.NET 4.6 Framework. 7th ed. Apress.

You might also like