lect8 Poly
Document Sample


1
Advanced Programming
Lecture 7
Inheritance
Abstract Classes and Methods
• Abstract classes
– Cannot be instantiated
– Used as base classes
– Class definitions are not complete – derived classes must
define the missing pieces
– Can contain abstract methods and/or abstract properties
• Have no implementation
• Derived classes must override inherited abstract methods and
properties to enable instantiation
Abstract Classes and Methods
• Concrete classes use the keyword override to
provide implementations for all the abstract
methods and properties of the base-class
• Any class with an abstract method or property
must be declared abstract
• Even though abstract classes cannot be
instantiated, we can use abstract class references
to refer to instances of any concrete class derived
from the abstract class
Case Study: Inheriting Interface and
Implementation
• Abstract base class Shape
– Concrete virtual method Area (default return value is 0)
– Concrete virtual method Volume (default return value is 0)
– Abstract read-only property Name
• Class Point2 inherits from Shape
– Overrides property Name (required)
– Does NOT override methods Area and Volume
• Class Circle2 inherits from Point2
– Overrides property Name
– Overrides method Area, but not Volume
• Class Cylinder2 inherits from Circle2
– Overrides property Name
– Overrides methods Area and Volume
Case Study: Payroll System
• Base-class Employee
– abstract
– abstract method Earnings
• Classes that derive from Employee
– Boss
– CommissionWorker
– PieceWorker
– HourlyWorker
• All derived-classes implement method Earnings
• Driver program uses Employee references to refer to
instances of derived-classes
• Polymorphism calls the correct version of Earnings
6
using System;
public abstract class Employee
{
private string firstName;
private string lastName;
public Employee( string firstNameValue,
string lastNameValue )
{
FirstName = firstNameValue;
LastName = lastNameValue;
}
public string FirstName
{
get
{
return firstName;
}
set
{
firstName = value;
}
}
7
public string LastName
{
get
{
return lastName;
}
set
{
lastName = value;
}
}
public string toString()
{
return FirstName + " " + LastName;
}
public abstract decimal Earnings();
}
8
using System;
public class Boss : Employee
{
private decimal salary;
public Boss( string firstNameValue, string stNameValue,
decimal salaryValue): base( firstNameValue,lastNameValue )
{
WeeklySalary = salaryValue;
}
public decimal WeeklySalary
{
get
{
return salary;
}
set
{
if ( value > 0 )
salary = value;
}
}
9
public override decimal Earnings()
{
return WeeklySalary;
}
public override string ToString()
{
return "Boss: " + base.ToString();
}
}
10
using System;
public class CommissionWorker : Employee
{
private decimal salary; // base weekly salary
private decimal commission; // amount paid per item sold
private int quantity; // total items sold
public CommissionWorker( string firstNameValue,
string lastNameValue, decimal salaryValue,
decimal commissionValue, int quantityValue )
: base( firstNameValue, lastNameValue )
{
WeeklySalary = salaryValue;
Commission = commissionValue;
Quantity = quantityValue;
}
public decimal WeeklySalary
{
get
{
return salary;
}
11
set
{
// ensure non-negative salary value
if ( value > 0 )
salary = value;
}
}
public decimal Commission
{
get
{
return commission;
}
set
{
if ( value > 0 )
commission = value;
}
}
public int Quantity
{
get
{
return quantity;
}
12
set
{
if ( value > 0 )
quantity = value;
}
}
public override decimal Earnings()
{
return WeeklySalary + Commission * Quantity;
}
public override string toString()
{
return "CommissionWorker: " + base.ToString();
}
} // end class CommissionWorker
13
using System;
public class PieceWorker : Employee
{
private decimal wagePerPiece; // wage per piece produced
private int quantity; // quantity of pieces
public PieceWorker( string firstNameValue,
string lastNameValue, decimal wagePerPieceValue,
int quantityValue )
: base( firstNameValue, lastNameValue )
{
WagePerPiece = wagePerPieceValue;
Quantity = quantityValue;
}
public decimal WagePerPiece
{
get
{
return wagePerPiece;
}
set
{
if ( value > 0 )
wagePerPiece = value;
}
}
14
public int Quantity
{
get
{
return quantity;
}
set
{
if ( value > 0 )
quantity = value;
}
}
public override decimal Earnings()
{
return Quantity * WagePerPiece;
}
public override string ToString()
{
return "PieceWorker: " + base.ToString();
}
}
15
using System;
public class HourlyWorker : Employee
{
private decimal wage; // wage per hour of work
private double hoursWorked; // hours worked during week
public HourlyWorker( string firstNameValue, string LastNameValue,
decimal wageValue, double hoursWorkedValue )
: base( firstNameValue, LastNameValue )
{
Wage = wageValue;
HoursWorked = hoursWorkedValue;
}
public decimal Wage
{
get
{
return wage;
}
set
{
if ( value > 0 )
wage = value;
}
}
16
public double HoursWorked
{
get
{
return hoursWorked;
}
set
{
if ( value > 0 )
hoursWorked = value;
}
}
public override decimal Earnings()
{
if ( HoursWorked <= 40 )
{
return Wage * Convert.ToDecimal( HoursWorked );
}
else
{
decimal basePay = Wage * Convert.ToDecimal( 40 );
decimal overtimePay = Wage * 1.5M *
Convert.ToDecimal( HoursWorked - 40 );
17
return basePay + overtimePay;
}
}
public override string toString()
{
return "HourlyWorker: " + base.ToString();
}
}
18
public class EmployeesTest {
public static void Main( string[] args ) {
Boss boss = new Boss( "John", "Smith", 800 );
CommissionWorker commissionWorker =
new CommissionWorker( "Sue", "Jones", 400, 3, 150 );
PieceWorker pieceWorker = new PieceWorker( "Bob","Lewis",
Convert.ToDecimal( 2.5 ), 200 );
HourlyWorker hourlyWorker = new HourlyWorker( "Karen",
"Price", Convert.ToDecimal( 13.75 ), 50 );
Employee employee = boss;
string output = GetString( employee ) + boss + " earned " +
boss.Earnings().ToString( "C" ) + "\n\n";
employee = commissionWorker;
output += GetString( employee ) + commissionWorker +
" earned " + commissionWorker.Earnings().ToString( "C" ) +
"\n\n";
employee = pieceWorker;
19
output += GetString( employee ) + pieceWorker +
" earned " + pieceWorker.Earnings().ToString( "C" ) + "\n\n";
employee = hourlyWorker;
output += GetString( employee ) + hourlyWorker +
" earned " + hourlyWorker.Earnings().ToString( "C" ) +"\n\n";
MessageBox.Show( output, "Demonstrating Polymorphism",
MessageBoxButtons.OK, MessageBoxIcon.Information );
} // end method Main
// return string that contains Employee information
public static string GetString( Employee worker )
{
return worker.ToString() + " earned " +
worker.Earnings().ToString( "C" ) + "\n";
}
}
20
String
21
using System;
using System.Windows.Forms;
class StringConstructor
{
static void Main( string[] args )
{
string output;
string originalString, string1, string2, string3, string4;
char[] characterArray = {'b', 'i', 'r', 't', 'h', ' ', 'd',
'a', 'y' };
StringConstruct
originalString = "Welcome to C# programming!";
or.cs
string1 = originalString;
string2 = new string( characterArray );
string3 = new string( characterArray, 6, 3 );
string4 = new string( 'C', 5 );
output = "string1 = " + "\"" + string1 + "\"\n" +
"string2 = " + "\"" + string2 + "\"\n" +
"string3 = " + "\"" + string3 + "\"\n" +
"string4 = " + "\"" + string4 + "\"\n";
String Indexer, Length Property and CopyTo
Method
• String indexer
– Retrieval of any character in the string
• Length property
– Returns the length of the string
• CopyTo
– Copies specified number of characters into a char array
23
using System;
using System.Windows.Forms;
class StringMethods
{
static void Main( string[] args )
{
string string1, output;
char[] characterArray;
string1 = "hello there";
characterArray = new char[ 5 ]; StringMethods.c
s
output = "string1: \"" + string1 + "\"";
output += "\nLength of string1: " + string1.Length;
output += "\nThe string reversed is: ";
for ( int i = string1.Length - 1; i >= 0; i-- )
output += string1[ i ];
Comparing Strings
• String comparison
– Greater than
– Less than
• Method Equals
– Test objects for equality
– Return a Boolean
– Uses lexicographical comparison
25
using System;
using System.Windows.Forms;
class StringCompare
{
static void Main( string[] args )
{
string string1 = "hello";
string string2 = "good bye";
string string3 = "Happy Birthday";
string string4 = "happy birthday";
string output;
// output values of four strings
StringCompare.c
output = "string1 = \"" + string1 + "\"" +
s
"\nstring2 = \"" + string2 + "\"" +
"\nstring3 = \"" + string3 + "\"" +
"\nstring4 = \"" + string4 + "\"\n\n";
// test for equality using Equals method
if ( string1.Equals( "hello" ) )
output += "string1 equals \"hello\"\n";
else
output += "string1 does not equal \"hello\"\n";
// test for equality with ==
if ( string1 == "hello" )
output += "string1 equals \"hello\"\n";
26
using System;
using System.Windows.Forms;
class StringStartEnd
{
static void Main( string[] args )
{
string[] strings = { "started", "starting", "ended", "ending" };
string output = "";
for ( int i = 0; i < strings.Length; i++ )
if ( strings[ i ].StartsWith( "st" ) )
output += "\"" + strings[ i ] + "\"" + " starts with \"st\"\n";
StringStartEnd.
output += "\n"; cs
// test every string to see if it ends with "ed“
for ( int i = 0; i < strings.Length; i ++ )
if ( strings[ i ].EndsWith( "ed" ) )
output += "\"" + strings[ i ] + "\"" +
" ends with \"ed\"\n";
Miscellaneous String Methods
• Method Replace
– Original string remain unchanged
– Original string return if no occurrence matched
• Method ToUpper
– Replace lower case letter
– Original string remain unchanged
– Original string return if no occurrence matched
• Method ToLower
– Replace lower case letter
– Original string remain unchanged
– Original string return if no occurrence matched
Miscellaneous String Methods
• Method ToString
– Can be called to obtain a string representation of any object
• Method Trim
– Remove whitespaces
– Remove characters in the array argument
29
using System;
using System.Windows.Forms;
class StringMethods2
{
static void Main( string[] args )
{
string string1 = "cheers!";
string string2 = "GOOD BYE ";
string string3 = " spaces ";
string output;
output = "string1 = \"" + string1 + "\"\n" +
StringMiscellan
"string2 = \"" + string2 + "\"\n" +
eous2.cs
"string3 = \"" + string3 + "\"";
// call method Replace
output +=
"\n\nReplacing \"e\" with \"E\" in string1: \"" +
string1.Replace( 'e', 'E' ) + "\"";
// call ToLower and ToUpper
output += "\n\nstring1.ToUpper() = \"" +
string1.ToUpper() + "\"\nstring2.ToLower() = \"" +
string2.ToLower() + "\"";
You have been provided with the following class that implements a
phone number directory:
public class PhoneBook {
public boolean insert(String phoneNum, String name) { ... }
public String getPhoneNumber(String name) { ... }
public String getName(String phoneNum) { ... }
// other private fields and methods }
• PhoneBook does not accept phone numbers that begin with "0" or
"1", that do not have exactly 10 digits. It does not allow duplicate
phone numbers. insert() returns true on a successful phone number
insertion, false otherwise. getPhoneNumber() and getName() return
null if they cannot find the desired entry in the PhoneBook.
• Design and implement a subclass of PhoneBook called YellowPages
(including all of the necessary fields and methods) that supports the
following additional operations.
• Retrieve the total number of phone numbers stored in the directory.
• Retrieve the percentage of phone numbers stored in the directory that
are "810" numbers (that have area code "810").
• Design an abstract class named BankAccount with data: balance,
number of deposits this month, number of withdrawals, annual
interest rate, and monthly service charges.
• The class has constructor and methods: Deposit (amount) {add
amount to balance and increment number of deposit by one},
Withdraw (amount) {subtract amount from balance and increment
number of withdrawals by one}, CalcInterest() { update balance by
amount = balance * (annual interest rate /12)}, and MonthlyPocess()
{subtract the monthly service charge from balance, call calcInterest
method, set number of deposit, number of withdrawals and monthly
service charges to zero}.
• Next, design a SavingAccount class which inherits from
BankAccount class. The class has Boolean status field to represent
the account is active or inactive {if balance falls below $25}. No
more withdrawals if account is inactive.
• The class has methods Deposit () {determine if account inactive then
change the status after deposit above $25, then call base deposit
method}, Withdraw() method check the class is active then call base
method, and MonthlyProcess() {check if number of withdrawals
more than 4, add to service charge $1 for each withdrawals above 4}
• Consider designing and implementing a set of classes to
represent books, library items, and library books.
• a) An abstract class library item contains two pieces of
information: a unique ID (string) and a holder (string). The
holder is the name of person who has checked out this item.
The ID can not change after it is created, but the holder can
change.
• b) A book class inherits from library item class. It contains
data author and title where neither of which can change once
the book is created. The class has a constructor with two
parameters author and title, and two methods getAuthor() to
return author value and getTitle() to return title value.
• c) A library book class is a book that is also a library item
(inheritance). Suggest the required data and method for this
class.
• d) A library is a collection of library books (Main class) which
has operations: add new library book to the library, check out a
library item by specifying its ID, determine the current holder
of library book given its ID
What will happen when you attempt to compile and
run this code?
class Base{
abstract public void myfunc();
public void another(){
console.writeline("Another method");
}
}
public class Abs : Base{
public static void main(String argv[]){
Abs a = new Abs();
a.amethod();
}
public void myfunc(){
console.writeline("My func");
}
public void amethod(){
myfunc();
}
}
Data Abstraction and Information Hiding
• Classes should hide implementation details
• Stacks
– Last-in, first-out (LIFO)
– Items are pushed onto the top of the stack
– Items are popped off the top of the stack
• Queues
– Similar to a waiting line
– First-in, first-out (FIFO)
– Items are enqueued (added to the end)
– Items are dequeued (taken off the front)
35
Derived-Class-Object to Base-Class-Object
Conversion
• Class hierarchies
– Can assign derived-class objects to base-class
references
– Can explicitly cast between types in a class hierarchy
• An object of a derived-class can be treated as an object of
its base-class
– Array of base-class references that refer to objects of
many derived-class types
– Base-class object is NOT an object of any of its derived
classes
36
using System;
// Point class definition implicitly inherits from Object
public class Point
{
// point coordinate
private int x, y;
// default constructor
public Point()
{
// implicit call to Object constructor occurs here
}
public Point( int xValue, int yValue )
{
// implicit call to Object constructor occurs here
X = xValue;
Y = yValue;
}
public int X
{
get
{
return x;
}
37
set
{
x = value; // no need for validation
}
} // end property X
// property Y
public int Y
{
get
{
return y;
}
set
{
y = value; // no need for validation
}
} // end property Y
// return string representation of Point
public override string ToString()
{
return "[" + X + ", " + Y + "]";
}
} // end class Point
38
using System;
// Circle class definition inherits from Point
public class Circle : Point
{
private double radius; // circle's radius
// default constructor
public Circle()
{
// implicit call to Point constructor occurs here
}
public Circle( int xValue, int yValue, double radiusValue )
: base( xValue, yValue )
{
Radius = radiusValue;
}
// property Radius
public double Radius
{
get
{
return radius;
}
39
set
{
if ( value >= 0 ) // validate radius
radius = value;
}
} // end property Radius
public double Diameter()
{
return Radius * 2;
}
public double Circumference()
{
return Math.PI * Diameter();
}
public virtual double Area()
{
return Math.PI * Math.Pow( Radius, 2 );
}
public override string ToString()
{
return "Center = " + base.ToString() +
"; Radius = " + Radius;
}
} // end class Circle
40
using System;
using System.Windows.Forms;
class PointCircleTest
{
// main entry point for application.
static void Main( string[] args )
{
Point point1 = new Point( 30, 50 );
Circle circle1 = new Circle( 120, 89, 2.7 );
string output = "Point point1: " + point1.ToString() +
"\nCircle circle1: " + circle1.ToString();
// use 'is a' relationship to assign
// Circle circle1 to Point reference
Point point2 = circle1;
output += "\n\nCCircle circle1 (via point2): " + point2.ToString();
// downcast (cast base-class reference to derived-class
// data type) point2 to Circle circle2
Circle circle2 = ( Circle ) point2;
output += "\n\nCircle circle1 (via circle2): " +
circle2.ToString();
output += "\nArea of circle1 (via circle2): " +
circle2.Area().ToString( "F" );
41
// attempt to assign point1 object to Circle reference
if ( point1 is Circle )
{
circle2 = ( Circle ) point1;
output += "\n\ncast successful";
}
else
{
output += "\n\npoint1 does not refer to a Circle";
}
MessageBox.Show( output, "Demonstrating the 'is a' relationship" );
} // end method Main
} // end class PointCircleTest
42
Interfaces
• Interfaces specify the public services (methods
and properties) that classes must implement
• Interfaces provide no default implementations vs.
abstract classes which may provide some default
implementations
• Interfaces are used to “bring together” or relate
disparate objects that relate to one another only
through the interface
43
Interfaces
• Interfaces are defined using keyword interface
• Use inheritance notation to specify a class
implements an interface (ClassName :
InterfaceName)
• Classes may implement more than one interface (a
comma separated list of interfaces)
• Classes that implement an interface, must provide
implementations for every method and property in
the interface definition
44
public interface Ishape
{
// classes that implement IShape must implement these methods
// and this property
double Area();
double Volume();
string Name { get; }
}
45
// an x-y coordinate pair.
using System;
public class Point3 : Ishape
{
private int x, y; // Point3 coordinates
public Point3()
{
}
// constructor
public Point3( int xValue, int yValue )
{
X = xValue;
Y = yValue;
}
// property X
public int X
{
get
{
return x;
}
46
32 set
33 {
34 x = value;
35 }
36 }
37
38 // property Y
39 public int Y
40 {
41 get
42 {
43 return y;
44 }
45
46 set
47 {
48 y = value;
49 }
50 }
51
52 // return string representation of Point3
object
53 public override string ToString()
54 {
47
64 // implement interface IShape method Volume
65 public virtual double Volume()
66 {
67 return 0;
68 }
69
70 // implement property Name of IShape
71 public virtual string Name
72 {
73 get
74 {
75 return "Point3";Implementation of IShape
76 } property Name (required),
77 } declared virtual to allow
78 deriving classes to
79 } // end class Point3 override
48
1 // Fig. 10.21: Circle3.cs
2 // Circle3 inherits from class Point3 and
overrides key members.
3 using System;
4
5 // Circle3 inherits from class Point3
6 public class Circle3 : Point3
7 {
8 private double radius; // Circle3 radius
9
10 // default constructor
11 public Circle3()
12 {
13 // implicit call to Point3 constructor
occurs here
14 }
15
16 // constructor
17 public Circle3( int xValue, int yValue, double
radiusValue )
18 : base( xValue, yValue )
19 {
20 Radius = radiusValue;
21 }
49
31 set
32 {
33 // ensure non-negative Radius value
34 if ( value >= 0 )
35 radius = value;
36 }
37 }
38
39 // calculate Circle3 diameter
40 public double Diameter()
41 {
42 return Radius * 2;
43 }
44
45 // calculate Circle3 circumference
46 public double Circumference()
47 {
48 return Math.PI * Diameter();
49 }
50
51 // calculate Circle3 area
52 public override double Area()
53 {
54 return Math.PI * Math.Pow( Radius, 2 );
50
64 // override property Name from class Point3
65 public override string Name
66 {
67 get
68 {
69 return "Circle3";
70 }
71 }
72
73 } // end class Circle3
51
1 // Fig. 10.22: Cylinder3.cs
2 // Cylinder3 inherits from class Circle2 and
overrides key members.
3 using System;
4
5 // Cylinder3 inherits from class Circle3
6 public class Cylinder3 : Circle3
7 {
8 private double height; // Cylinder3 height
9
10 // default constructor
11 public Cylinder3()
12 {
13 // implicit call to Circle3 constructor
occurs here
14 }
15
16 // constructor
17 public Cylinder3( int xValue, int yValue,
double radiusValue,
18 double heightValue ) : base( xValue, yValue,
radiusValue )
19 {
20 Height = heightValue;
52
31 set
32 {
33 // ensure non-negative Height value
34 if ( value >= 0 )
35 height = value;
36 }
37 }
38
39 // calculate Cylinder3 area
40 public override double Area()
41 {
42 return 2 * base.Area() +
base.Circumference() * Height;
43 }
44
45 // calculate Cylinder3 volume
46 public override double Volume()
47 {
48 return base.Area() * Height;
49 }
50
51 // return string representation of Cylinder3
object
52 public override string ToString()
53
58 // override property Name from class Circle3
59 public override string Name
60 {
61 get
62 {
63 return "Cylinder3";
64 }
65 }
66
67 } // end class Cylinder3
54
1 // Fig. 10.23: Interfaces2Test.cs
2 // Demonstrating polymorphism with interfaces in
3 // Point-Circle-Cylinder hierarchy.
4
5 using System.Windows.Forms;
6
7 public class Interfaces2Test
8 {
9 public static void Main( string[] args )
10 {
11 // instantiate Point3, Circle3 and Cylinder3
objects
12 Point3 point = new Point3( 7, 11 );
13 Circle3 circle = new Circle3( 22, 8, 3.5 );
14 Cylinder3 cylinder = new Cylinder3( 10, 10,
3.3, 10 );
15
16 // create array of IShape references
17 IShape[] arrayOfShapes = new IShape[ 3 ];
18
19 // arrayOfShapes[ 0 ] references Point3
object
20 arrayOfShapes[ 0 ] = point;
21
55
32 foreach ( IShape shape in arrayOfShapes )
33 {
34 output += "\n\n" + shape.Name + ":\nArea
= " +
35 shape.Area() + "\nVolume = " +
shape.Volume();
36 }
37
38 MessageBox.Show( output, "Demonstrating
Polymorphism" );
39 }
40 }
Get documents about "