Chapter 11 ObjectOriented Programming Polymorphism Interfaces Operator Overloading
Chapter 11 – [Object-Oriented Programming] Polymorphism, Interfaces & Operator Overloading Section [order of the slides consistent with ed. 1 of the textbook] 11. 1 Introduction [10. 2 in ed. 1] Derived-Class-Object to Base-Class-Object Conversion [10. 3 in ed. 1] Type Fields and switch Statements 11. 2 Polymorphism Examples 11. 4 Abstract Classes and Methods [10. 6 in ed. 1] Case Study: Inheriting from an Abstract Class and Implementation 11. 6 sealed Methods and Classes 11. 5 Case Study: Payroll System Using Polymorphism 11. 7 Case Study: Creating and Using Interfaces [10. 10 in ed. 1] Delegates 11. 8 Operator Overloading Many slides modified by Prof. L. Lilien (even many without explicit message). 2002 Prentice Hall. All rights reserved. Slides added by L. Lilien are © 2006 Leszek T. Lilien. Permision to use for non-commercial purposes slides added by L. Lilien’s will be gladly granted upon a written (e. g. , emailed) request. 1
2 11. 1. Introduction • Polymorphism – Poly = many , morph = form – Polymorphic = having many forms • Example: – Base class: Quadrilateral – Derived classes: Rectangle, Square, Trapezoid – Polymorhpic “Quadrilateral. Draw. Yourself” method • 3 (“many”) forms of Draw. Yourself for 3 classes derived from Quadrilateral – “Quadrilateral. Draw. Yourself” morphs (re-forms, reshapes) to fit the class of the object for which it is called • Becomes Quadrilateral. Rectangle for a Rectangle object • Becomes Quadrilateral. Square for a Square object • Becomes Quadrilateral. Trapezoid for a Trapezoid object 2002 Prentice Hall. All rights reserved. Slide added by L. Lilien
3 • Polymorphism – allows programmers to write: – Programs that handle a wide variety of related classes in a generic manner – Systems that are easily extensible 2002 Prentice Hall. All rights reserved.
[10. 2 in textbook ed. 1] Derived-Class-Object to Base-Class-Object Conversion • Class hierarchies – Can assign derived-class objects to base-class references - A fundamental part of programs that process objects polymorphically – 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 (The reverse is NOT true, i. e. : base-class object is NOT an object of any of its derived classes) – Can have arrays of base-class references that refer to objects of many derived-class types (we’ll see in 10. 4 & 10. 6) 2002 Prentice Hall. All rights reserved. Slide modified by L. Lilien 4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 // Fig. 10. 1: Point. cs [in textbook ed. 1] // Point class represents an x-y coordinate Definition pair. of class Point using System; Outline Point. cs // 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 } // constructor public Point( int x. Value, int y. Value ) { // implicit call to Object constructor occurs here X = x. Value; Y = y. Value; } // property X public int X { get { return x; } 2002 Prentice Hall. All rights reserved. 5
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 set { x = value; } Outline // no need for validation Point. cs } // 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 To. String() { return "[" + X + ", " + Y + "]"; } } // end class Point 2002 Prentice Hall. All rights reserved. 6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 // Fig. 10. 2: Circle. cs [in textbook ed. 1] // Circle class that inherits from class Point. Definition of class using System; Circle which inherits from class Point Outline Circle. cs // 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 } // constructor public Circle( int x. Value, int y. Value, double radius. Value ) : base( x. Value, y. Value ) { Radius = radius. Value; } // property Radius public double Radius { get { return radius; } 2002 Prentice Hall. All rights reserved. 7
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 Outline set { if ( value >= 0 ) // validate radius = value; } Circle. cs } // end property Radius // calculate Circle diameter public double Diameter() { return Radius * 2; } // calculate Circle circumference public double Circumference() { return Math. PI * Diameter(); } // calculate Circle area public virtual double Area() { return Math. PI * Math. Pow( Radius, 2 ); } // return string representation of Circle public override string To. String() { return "Center = " + base. To. String() + "; Radius = " + Radius; } } // end class Circle 2002 Prentice Hall. All rights reserved. 8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // Fig. 10. 3: Point. Circle. Test. cs [in textbook ed. 1] // Demonstrating inheritance and polymorphism. Outline 9 using System; using System. Windows. Forms; Create a Point object Point. Circle. Test. Assign Circle // Point. Circle. Test class definition cs Createcircle 1 a Circle object (derived-class Point. Circle. Test { object) to Point // main entry point for application. Use base-class reference to point 2 reference (base. Casts (“downcasts”) Point static void Main( string[] args ) access a derived-class object { class object reference) object point 2 (which (see slide 11) Point point 1 = new Point( 30, 50 ); OK since a. Circle is-a references Circle object Circle circle 1 = new Circle( 120, 89, 2. 7 ); Point to a Circle circle 1) string output = "Point point 1: " + point 1. To. String() + result to and then assigns the "n. Circle circle 1: " + circle 1. To. String(); the Circle reference // use 'is a' relationship to assign circle 2. (Cast would be // Circle circle 1 to Point reference dangerous if point 2 were Point point 2 = circle 1; referencing a Point! It is OK since" point 2 output += "nn. CCircle circle 1 (via point 2): + point 2. To. String(); // Circle’s To. String called, not Point’s references a Circle) // To. String, since point 2 references now a Circle object (circle 1). // (Object type determines method version, not reference type. ) 25 26 27 28 29 30 31 32 33 34 35 // downcast (cast base-class reference to derived-class // data type) point 2 to Circle circle 2 = ( Circle ) point 2; output += "nn. Circle circle 1 (via circle 2 [and point 2]): " + circle 2. To. String(); output += "n. Area of circle 1 (via circle 2): " + circle 2. Area(). To. String( "F" ); Slide modified by L. Lilien 2002 Prentice Hall. All rights reserved.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 Outline // attempt to assign point 1 object to Circle reference if ( point 1 is Circle ) { circle 2 = ( Circle ) point 1; // Incorrect! Objects may be // cast only to their own type or their base-class types. // Here, point 1’s own type is Point, and Circle // is not a base-class type for Point. output += "nncast successful"; } else { output += "nnpoint 1 does not refer to a Circle" ; } Test if point 1 references a Message. Box. Show( output, "Demonstrating the 'is a' relationship" object –); it does not since } // end method Main 10 Point. Circle. Test. cs Circle point 1 references a Point object ( l. 13) } // end class Point. Circle. Test Program Output Slide modified by L. Lilien 2002 Prentice Hall. All rights reserved.
NOTE: All pages – textbook ed. 1 11 Object (namespace: System) Point – p. 384 Circle – p. 385 implicit inheritance explicit inheritance Notes on Point. Circle. Test (p. 387): 1) l. 21: Point point 2 = circle 1; - uses 'is a' relationship to assign Circle circle 1 (derived-class object) to Point point 2 reference (base-class object reference). 2) l. 24: point 2. To. String(); - Circle’s To. String() method called, not Point’s To. String(), since point 2 references at that point a Circle object (circle 1). Object type, not reference type, determines method version. This is an example of polymorphism. 3) l. 28: Circle circle 2 = (Circle) point 2; – casts (“downcasts”) Point object point 2 (which references a Circle object circle 1) to a Circle and then assigns the result to the Circle reference circle 2. Cast would be dangerous if point 2 were referencing a Point! (but it references a Circle – see l. 21) 4) l. 37: if ( point 1 is Circle ) - tests if the object referenced by point 1 is-a Circle (i. e. , is an object of the Circle class) 5) l. 37: circle 2 = ( Circle ) point 1; - Incorrect! Objects may be cast only to their own type or the base-class types. Here, point 1’s own type is Point, and Circle is not a base-class type for Point. Line 37 would cause an execution error if it were executed. But it is never executed (do you know why? ). 2002 Prentice Hall. All rights reserved. Slide added by L. Lilien
12 point 1 Point point 1 (object itself) circle 1 Circle circle 1 (object itself) point 2 circle 2 a reference 2002 Prentice Hall. All rights reserved. Slide added by L. Lilien
[10. 3 in textbook ed. 1] Type Fields and switch Statements • Using switch to determine the type of an object – Distinguish between object types, then perform appropriate action depending on object type • Potential problems using switch – Programmer may forget to include a type test – Programmer may forget to test all possible cases in a switch – When new types are added, programmer may forget to modify all relevant switch structures – Every addition or deletion of a class requires modification of every switch statement determining object types in the system; tracking this is time consuming and error prone 2002 Prentice Hall. All rights reserved. 13
11. 2. Polymorphism Examples (Example 1) • Quadrilateral base-class contains method perimeter – Rectangle derived-class (implements perimeter) – Square derived-class (implements perimeter) – Parallelogram derived-class (implements perimeter) – Trapezoid derived-class (implements perimeter) Object (namespace: System) Quadrilateral Rectangle Square Parallelogram Trapezoid implicit inheritance explicit inheritance 2002 Prentice Hall. All rights reserved. Figure added by L. Lilien 14
15 • Any other operation (e. g. , perimeter ) that can be performed on a Quadrilateral object can also be performed on a Rectangle, Square, Parallelogram, or Trapezoid object • Suppose that: [added by L. Lilien] – Program P instantiated a Rectangle/ Square/… object referenced via rectangle 1/square 1/…: • Rectangle rectangle 1 = new Rectangle (…); Square square 1 = new Square (…); – P can use a base-class reference quad 1 to invoke derived-class methods Rectangle. perimeter, Square. perimeter, … • Quadrilateral quad 1 = rectangle 1; … quad 1. perimeter … // Method perimeter is executed // on the derived-class object rectangle 1 via the // base-class reference quad 1. perimeter Quadrilateral quad 1 = square 1; … quad 1. perimeter … // Method perimeter is executed // on the derived-class object square 1 via the // same base-class reference quad 1. perimeter – With such a Quadrilateral reference, C# polymorphically chooses the correct overriding method in any of these derived-classes from which the object is instantiated 2002 Prentice Hall. All rights reserved. Slide modified by L. Lilien
11. 2 Polymorphism Examples (Example 2) • Space. Object base-class – contains method Draw. Yourself – – Martian derived-class (implements Draw. Yourself) Venutian derived-class (implements Draw. Yourself) Plutonian derived-class (implements Draw. Yourself) Space. Ship derived-class (implements Draw. Yourself) Object (namespace: System) Space. Object Martian Venutian implicit inheritance explicit inheritance 2002 Prentice Hall. All rights reserved. Plutonian Space. Ship Figure added by L. Lilien 16
17 • A screen-manager program may contain a Space. Object array of references to objects of various classes that derive from Space. Object – arr. Of. Space. Objects[ … 0 1 2 3 4 ] ] ] = = = martian 1; martian 2; venutian 1; plutonian 1; space. Ship 1; Listing added by L. Lilien • To refresh the screen, the screen-manager calls Draw. Yourself on each object in the array Listing added by L. Lilien – foreach(Space. Object space. Object in arr. Of. Space. Objects) { space. Object. Draw. Yourself } • The program polymorphically calls the appropriate version of Draw. Yourself on each object, based on the type of that object 2002 Prentice Hall. All rights reserved.
18 11. 4. 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 abstract properties to enable instantiation – Abstract methods and abstract properties are implicitly virtual (p. 395/1) 2002 Prentice Hall. All rights reserved. Slide modified by L. Lilien
19 • An abstract class is used to provide an appropriate base class from which other classes may inherit (concrete classes) • Abstract base classes are too generic to define (by instantiation) real objects • To define an abstract class, use keyword abstract in the declaration • To declare a method or property abstract, use keyword abstract in the declaration • Abstract methods and properties have no implementation 2002 Prentice Hall. All rights reserved.
20 • 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 2002 Prentice Hall. All rights reserved.
[10. 6 in textbook ed. 1] Case Study: Inheriting from an Abstract Class & Implementation [see Fig. - next slide] • 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 Point 2 inherits from Shape – Overrides abstract property Name (required) – Does NOT override methods Area and Volume • Area = 0 and Volume =0 are correct for a point • Class Circle 2 inherits from Point 2 – Overrides property Name – Overrides method Area, but not Volume • Volume =0 is correct for a circle • Class Cylinder 2 inherits from Circle 2 – Overrides property Name – Overrides methods Area and Volume 2002 Prentice Hall. All rights reserved. 21
22 NOTE: All pages – textbook ed. 1 Object (namespace: System) implicit inheritance explicit inheritance abstract class Shape (p. 394) Concrete virtual method Area Concrete virtual method Volume Abstract read-only property Name class Point 2 (p. 395) Overrides abstract property Name (required) Does NOT override methods Area and Volume (Default return values Area = 0 & Volume =0 are correct for a point) class Circle 2 (p. 397) Overrides property Name Overrides method Area, but not Volume (Volume =0 is correct for a circle) class Cylinder 2 (p. 398) Overrides property Name Overrides methods Area and Volume 2002 Prentice Hall. All rights reserved. Slide added by L. Lilien
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Outline // Fig. 10. 4: Shape. cs [in textbook ed. 1] // Demonstrate a shape hierarchy using an abstract base class. using System; public abstract class Shape { // return Shape's area public virtual double Area() { return 0; } // return Shape's volume public virtual double Volume() { return 0; } Declaration of virtual methods Area and Volume with default implementations Shape. cs Declaration of read-only (get) abstract property Name; implementing classes will have to provide an implementation for this property Declaration of abstract class Shape // return Shape's name public abstract string Name { get; } } 2002 Prentice Hall. All rights reserved. 23
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 // Fig. 10. 5: Point 2. cs [in textbook ed. 1] // Point 2 inherits from abstract class Shape and represents // an x-y coordinate pair. using System; Outline Point 2. cs // Point 2 inherits from abstract class Shape public class Point 2 : Shape { private int x, y; // Point 2 coordinates // default constructor public Point 2() { // implicit call to Object constructor occurs here } // constructor public Point 2( int x. Value, int y. Value ) { X = x. Value; Y = y. Value; } Class Point 2 inherits from class Shape // property X public int X { get { return x; } set { x = value; // no validation needed } 2002 Prentice Hall. All rights reserved. 24
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 Outline } // property Y public int Y { get { return y; } Point 2’s implementation of the read-only Name property Point 2. cs set { y = value; // no validation needed } } // return string representation of Point 2 object public override string To. String() { return "[" + X + ", " + Y + "]"; } // implement abstract property Name of class Shape public override string Name { get { return "Point 2"; } } } // end class Point 2 2002 Prentice Hall. All rights reserved. 25
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 // Fig. 10. 6: Circle 2. cs [in textbook ed. 1] // Circle 2 inherits from class Point 2 and overrides key members. using System; // Circle 2 inherits from class Point 2 public class Circle 2 : Point 2 { private double radius; // Circle 2 radius Outline Circle 2. cs // default constructor public Circle 2() { // implicit call to Point 2 constructor occurs here } // constructor public Circle 2( int x. Value, int y. Value, double radius. Value ) : base( x. Value, y. Value ) { Radius = radius. Value; Definition of class Circle 2 which } // property Radius public double Radius { get { return radius; } inherits from class Point 2 2002 Prentice Hall. All rights reserved. 26
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 } set { // ensure non-negative radius value if ( value >= 0 ) radius = value; } Override Outline Circle 2. cs the Area method (defined in class Shape) // calculate Circle 2 diameter public double Diameter() { return Radius * 2; } // calculate Circle 2 circumference public double Circumference() { return Math. PI * Diameter(); } // calculate Circle 2 area public override double Area() { return Math. PI * Math. Pow( Radius, 2 ); } // return string representation of Circle 2 object public override string To. String() { return "Center = " + base. To. String() + "; Radius = " + Radius; } 2002 Prentice Hall. All rights reserved. 27
63 64 65 66 67 68 69 70 71 72 73 // override property Name from class Point 2 public override string Name { get { return "Circle 2"; } } } // end class Circle 2 Outline Circle 2. cs Override the read-only Name property 2002 Prentice Hall. All rights reserved. 28
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 // Fig. 10. 7: Cylinder 2. cs [in textbook ed. 1] // Cylinder 2 inherits from class Circle 2 and overrides key members. using System; // Cylinder 2 inherits from class Circle 2 public class Cylinder 2 : Circle 2 { private double height; // Cylinder 2 height Outline Cylinder 2. cs // default constructor public Cylinder 2() { // implicit call to Circle 2 constructor occurs here } // constructor public Cylinder 2( int x. Value, int y. Value, double radius. Value, double height. Value ) : base( x. Value, y. Value, radius. Value ) { Height = height. Value; } // property Height public double Height { get { return height; } Class Cylinder 2 derives from Circle 2 set { // ensure non-negative height value if ( value >= 0 ) height = value; 2002 Prentice Hall. All rights reserved. 29
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 Outline } } Override read-only property Name // calculate Cylinder 2 area public override double Area() { return 2 * base. Area() + base. Circumference() * Height; } Cylinder 2. cs // calculate Cylinder 2 volume public override double Volume() { return base. Area() * Height; } // return string representation of Circle 2 object public override string To. String() { return base. To. String() + "; Height = " + Height; } // override property Name from class Circle 2 public override string Name { get Override Area implementation of class { return "Cylinder 2"; } } Override Volume implementation of class Shape Circle 2 } // end class Cylinder 2 2002 Prentice Hall. All rights reserved. 30
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 // Fig. 10. 8: Abstract. Shapes. Test. cs [in textbook ed. 1] // Demonstrates polymorphism in Point-Circle-Cylinder hierarchy. using System; using System. Windows. Forms; Assign a Shape reference to Create an array of Shape objects Outline 31 Abstract. Shapes. Te st. cs reference a Point 2 object public class Abstract. Shapes. Test { Assign a Shape reference to public static void Main( string[] args ) Assign a a. Shape reference to reference Cylinder 2 object { reference a Circle 2 object // instantiate Point 2, Circle 2 and Cylinder 2 objects Point 2 point = new Point 2( 7, 11 ); Circle 2 circle = new Circle 2( 22, 8, 3. 5 ); Cylinder 2 cylinder = new Cylinder 2( 10, 3. 3, 10 ); // create empty array of Shape base-class references Shape[] array. Of. Shapes = new Shape[ 3 ]; // array. Of. Shapes[ 0 ] refers to Point 2 object array. Of. Shapes[ 0 ] = point; // array. Of. Shapes[ 1 ] refers to Circle 2 object array. Of. Shapes[ 1 ] = circle; // array. Of. Shapes[ 1 ] refers to Cylinder 2 object array. Of. Shapes[ 2 ] = cylinder; string output = point. Name + ": " + point + "n" + circle. Name + ": " + circle + "n" + cylinder. Name + ": " + cylinder; Slide modified by L. Lilien 2002 Prentice Hall. All rights reserved.
31 32 33 34 35 36 37 38 39 40 41 42 // display Name, Area and Volume for each object // in array. Of. Shapes polymorphically foreach( Shape shape in array. Of. Shapes ) { output += "nn" + shape. Name + ": " + shape + "n. Area = " + shape. Area(). To. String( "F" ) + "n. Volume = " + shape. Volume(). To. String( "F" ); } Outline Abstract. Shapes. Te st. cs Message. Box. Show( output, "Demonstrating Polymorphism" ); } } Use a foreach loop to access every element of the array 32 Rely on polymorphism to call appropriate version of methods Program Output 2002 Prentice Hall. All rights reserved.
33 11. 6. sealed Methods and Classes • sealed is a keyword in C# • sealed methods and sealed classes 1)sealed methods cannot be overridden in a derived class • Methods that are declared static or private are implicitly sealed 2)sealed classes cannot have any derived-classes • Creating sealed classes can allow some runtime optimizations – e. g. , virtual method calls can be transformed into non-virtual method calls Slide modified by L. Lilien 2002 Prentice Hall. All rights reserved.
34 STUDY ON YOUR OWN: 11. 5. Case Study: Payroll System Using Polymorphism • Base-class Employee – abstract method Earnings • Classes that derive from Employee – – Boss Commission. Worker Piece. Worker Hourly. Worker • All derived-classes implement method Earnings • Driver program uses Employee base-class references to refer to instances of derived-classes • Polymorphically calls the correct version of Earnings 2002 Prentice Hall. All rights reserved.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 // Fig. 10. 9: Employee. cs [in textbook ed. 1] // Abstract base class for company employees. using System; Outline Employee. cs public abstract class Employee { private string first. Name; private string last. Name; // constructor public Employee( string first. Name. Value, string last. Name. Value ) { First. Name = first. Name. Value; Last. Name = last. Name. Value; } Definition of abstract class Employee // property First. Name public string First. Name { get { return first. Name; } set { first. Name = value; } } 2002 Prentice Hall. All rights reserved. 35
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 // property Last. Name public string Last. Name { get { return last. Name; } Outline Declaration of abstract class Earnings – implementation must be provided by all derived classes Employee. cs set { last. Name = value; } } // return string representation of Employee public override string To. String() { return First. Name + " " + Last. Name; } // abstract method that must be implemented for each derived // class of Employee to calculate specific earnings public abstract decimal Earnings(); } // end class Employee 2002 Prentice Hall. All rights reserved. 36
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 // Fig. 10: Boss. cs [in textbook ed. 1] // Boss class derived from Employee. using System; public class Boss : Employee { private decimal salary; // Boss's salary Outline Boss. cs // constructor public Boss( string first. Name. Value, string last. Name. Value, decimal salary. Value) : base( first. Name. Value, last. Name. Value ) { Weekly. Salary = salary. Value; } // property Weekly. Salary public decimal Weekly. Salary { get { return salary; } Definition of class Boss – derives from Employee set { // ensure positive salary value if ( value > 0 ) salary = value; } } 2002 Prentice Hall. All rights reserved. 37
33 34 35 36 37 38 39 40 41 42 43 44 // override base-class method to calculate Boss's earnings public override decimal Earnings() { return Weekly. Salary; } Outline Boss. cs // return string representation of Boss public override string To. String() { return "Boss: " + base. To. String(); } } Implementation of abstract base-class method Earnings (required by classes deriving from Employee) 2002 Prentice Hall. All rights reserved. 38
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 // Fig. 10. 11: Commision. Worker. cs [in textbook ed. 1] // Commission. Worker class derived from Employee using System; public class Commission. Worker : Employee { private decimal salary; // base weekly salary private decimal commission; // amount paid per item sold private int quantity; // total items sold Outline Commision. Worker. cs // constructor public Commission. Worker( string first. Name. Value, string last. Name. Value, decimal salary. Value, decimal commission. Value, int quantity. Value ) : base( first. Name. Value, last. Name. Value ) { Weekly. Salary = salary. Value; Commission = commission. Value; Quantity = quantity. Value; } // property Weekly. Salary public decimal Weekly. Salary { get { return salary; } 39 Definition of class Commission. Worker – derives from Employee 2002 Prentice Hall. All rights reserved.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 set { // ensure non-negative salary value if ( value > 0 ) salary = value; } Outline 40 Commision. Worker. cs } // property Commission public decimal Commission { get { return commission; } set { // ensure non-negative commission value if ( value > 0 ) commission = value; } } // property Quantity public int Quantity { get { return quantity; } 2002 Prentice Hall. All rights reserved.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 set { // ensure non-negative quantity value if ( value > 0 ) quantity = value; } Outline 41 Commision. Worker. cs } // override base-class method to calculate // Commission. Worker's earnings public override decimal Earnings() { return Weekly. Salary + Commission * Quantity; } // return string representation of Commission. Worker public override string To. String() { return "Commission. Worker: " + base. To. String(); } Implementation of method Earnings (required by classes deriving from Employee) } // end class Commission. Worker 2002 Prentice Hall. All rights reserved.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 // Fig. 10. 12: Piece. Worker. cs [in textbook ed. 1] // Piece. Worker class derived from Employee. using System; public class Piece. Worker : Employee { private decimal wage. Per. Piece; // wage per piece produced private int quantity; // quantity of pieces produced Outline Piece. Worker. cs // constructor public Piece. Worker( string first. Name. Value, string last. Name. Value, decimal wage. Per. Piece. Value, int quantity. Value ) : base( first. Name. Value, last. Name. Value ) { Wage. Per. Piece = wage. Per. Piece. Value; Quantity = quantity. Value; } Definition of class Piece. Worker // property Wage. Per. Piece – derives public decimal Wage. Per. Piece { get { return wage. Per. Piece; } from Employee set { if ( value > 0 ) wage. Per. Piece = value; } } 2002 Prentice Hall. All rights reserved. 42
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 Outline // property Quantity public int Quantity { get { return quantity; } Piece. Worker. cs set { if ( value > 0 ) quantity = value; } } // override base-class method to calculate // Piece. Worker's earnings public override decimal Earnings() { return Quantity * Wage. Per. Piece; } // return string representation of Piece. Worker public override string To. String() { return "Piece. Worker: " + base. To. String(); } } Implementation of method Earnings (required by classes deriving from Employee) 2002 Prentice Hall. All rights reserved. 43
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 // Fig. 10. 13: Hourly. Worker. cs [in textbook ed. 1] // Hourly. Worker class derived from Employee. using System; public class Hourly. Worker : Employee { private decimal wage; // wage per hour of work private double hours. Worked; // hours worked during week Outline Hourly. Worker. cs // constructor public Hourly. Worker( string first. Name. Value, string Last. Name. Value, decimal wage. Value, double hours. Worked. Value ) : base( first. Name. Value, Last. Name. Value ) { Wage = wage. Value; Hours. Worked = hours. Worked. Value; } // property Wage public decimal Wage { get { return wage; } 44 Definition of class Hourly. Worker – derives from Employee set { // ensure non-negative wage value if ( value > 0 ) wage = value; } } 2002 Prentice Hall. All rights reserved.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 Outline // property Hours. Worked public double Hours. Worked { get { return hours. Worked; } 45 Hourly. Worker. cs set { // ensure non-negative hours. Worked value if ( value > 0 ) hours. Worked = value; } } // override base-class method to calculate // Hourly. Worker earnings public override decimal Earnings() { // compensate for overtime (paid "time-and-a-half") if ( Hours. Worked <= 40 ) { return Wage * Convert. To. Decimal( Hours. Worked ); } // Above: class Convert from the System namespace. Implementation of method Earnings (required by classes deriving from Employee) else { // calculate base and overtime pay decimal base. Pay = Wage * Convert. To. Decimal( 40 ); decimal overtime. Pay = Wage * 1. 5 M * Convert. To. Decimal( Hours. Worked - 40 ); 2002 Prentice Hall. All rights reserved.
68 69 70 71 72 73 74 75 76 77 return base. Pay + overtime. Pay; } Outline 46 } // return string representation of Hourly. Worker public override string To. String() { return "Hourly. Worker: " + base. To. String(); } Hourly. Worker. cs } 2002 Prentice Hall. All rights reserved.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 • 24 25 • 27 28 29 30 31 32 33 34 // Fig. 10. 14: Employees. Test. cs [in textbook ed. 1] // Demonstrates polymorphism by displaying earnings // for various Employee types. using System; using System. Windows. Forms; Assign Employee reference to Outline 47 Employees. Test. cs public class Employees. Test reference a Boss object { public static void Main( string[] args ) { Use method Get. String Boss boss = new Boss( "John", "Smith", 800 ); to polymorphically obtain salary information. Then use the original Boss reference to obtain the information Commission. Worker commission. Worker = new Commission. Worker( "Sue", "Jones", 400, 3, 150 ); Piece. Worker piece. Worker = new Piece. Worker( "Bob", "Lewis", Convert. To. Decimal( 2. 5 ), 200 ); Hourly. Worker hourly. Worker = new Hourly. Worker( "Karen", "Price", Convert. To. Decimal( 13. 75 ), 50 ); Employee employee = boss; // Get. String used below is defined in Lines 51 -55. // “C” produces default currency format (2 decimal places) string output = Get. String( employee ) + boss + " earned " + boss. Earnings(). To. String( "C" ) + "nn"; // Get. String() prepares first output line, the rest // produces identical second line – see output. employee = commission. Worker; output += Get. String( employee ) + commission. Worker + " earned " + commission. Worker. Earnings(). To. String( "C" ) + "nn"; employee = piece. Worker; 2002 Prentice Hall. All rights reserved.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 output += Get. String( employee ) + piece. Worker + " earned " + piece. Worker. Earnings(). To. String( "C" ) + "nn"; employee = hourly. Worker; Outline 48 Definition of method Get. String, which takes as an argument an Employees. Test. cs Employee object. output += Get. String( employee ) + hourly. Worker + " earned " + hourly. Worker. Earnings(). To. String( "C" ) + "nn"; Polymorphically call the method of "Demonstrating Polymorphism" , the appropriate derived class Message. Box. Show( output, Message. Box. Buttons. OK, Message. Box. Icon. Information ); } // end method Main // return string that contains Employee information public static string Get. String( Employee worker ) { return worker. To. String() + " earned " + worker. Earnings(). To. String( "C" ) + "n"; } } Program Output 2002 Prentice Hall. All rights reserved.
11. 7. Case Study: Creating and Using Interfaces 49 • Interfaces specify the public services (methods and properties) that classes must implement • Interfaces vs. abstract classes w. r. t default implementations – Interfaces provide no default implementations – Abstract classes may provide some default implementations • If no default implementations can/are defined – do not use an abstract class, use an interface instead • Interfaces are used to “bring together” or relate to each other disparate objects that relate to one another only through the interface – I. e. , provide uniform set of methods and properties for disparate objects – E. g. : A person and a tree are disparate objects Interface can define age and name for these disparate objects – Enables polymorphic processing of age and name for person & tree objects 2002 Prentice Hall. All rights reserved. Slide modified by L. Lilien
50 • Interfaces are defined using keyword interface • Use inheritance notation to specify that a class implements an interface Class. Name : Interface. Name • Classes may implement more then one interface: e. g. : Class. Name : Interface. Name 1, Interface. Name 2 – Can also have: • Class. Name : Class. Name 1, Class. Name 2, Interface. Name 1, Interface. Name 2 (object list must precedes interface list) • A class that implement an interface, must provide implementations for every method and property in the interface definition • Example: interface IAge that returns information about an object’s age – Can be used by classes for people, cars, trees (all have an age) 2002 Prentice Hall. All rights reserved. Slide modified by L. Lilien
1 2 3 4 5 6 7 8 // Fig. 10. 15: IAge. cs [in textbook ed. 1] // Interface IAge declares property for setting and getting age. public interface IAge { int Age { get; } string Name { get; } } Definition of interface IAge Outline IAge. cs Classes implementing this interface will have to define read-only properties Age and Name 2002 Prentice Hall. All rights reserved. 51
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 // Fig. 10. 16: Person. cs [in textbook ed. 1] // Class Person has a birthday. using System; Definition of Age property (required) public class Person : IAge { private string first. Name; private string last. Name; private int year. Born; Outline Person. cs Class Person implements the IAge interface // constructor public Person( string first. Name. Value, string last. Name. Value, int year. Born. Value ) { first. Name = first. Name. Value; last. Name = last. Name. Value; if ( year. Born. Value > 0 && year. Born. Value <= Date. Time. Now. Year ) year. Born = year. Born. Value; else year. Born = Date. Time. Now. Year; } // property Age implementation of interface IAge public int Age { get { return Date. Time. Now. Year - year. Born; } } 2002 Prentice Hall. All rights reserved. 52
33 34 35 36 37 38 39 40 41 42 // property Name implementation of interface IAge public string Name { get { return first. Name + " " + last. Name; } } } // end class Person Outline Person. cs Definition of Name property (required) 2002 Prentice Hall. All rights reserved. 53
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 Outline // Fig. 10. 17: Tree. cs [in textbook ed. 1] // Class Tree contains number of rings corresponding to its age. using System; public class Tree : IAge { private int rings; // number of rings in tree trunk Implementation // constructor public Tree( int year. Planted ) { // count number of rings in Tree rings = Date. Time. Now. Year - year. Planted; } // increment rings public void Add. Ring() { rings++; } Tree. cs of Age property ( required) Class Tree implements the IAge interface // property Age implementation of interface IAge public int Age { get { return rings; } } 2002 Prentice Hall. All rights reserved. 54
30 31 32 33 34 35 36 37 38 39 40 // property Name implementation of interface IAge public string Name { get { return "Tree"; } } } // end class Tree Outline Tree. cs Definition of Name property (required) 2002 Prentice Hall. All rights reserved. 55
Outline 56 1 // Fig. 10. 18: Interfaces. Test. cs [in textbook ed. 1] 2 // Demonstrating polymorphism with interfaces (on the objects of // disparate classes Tree and Person). 3 using System. Windows. Forms; Create array of IAge references 4 Interfaces. Test. c 5 public class Interfaces. Test Assign an IAge reference to s 6 { Assign an IAge reference to 7 public static void Main( string[] args ) reference a Person object reference a Tree object 8 { 9 Tree tree = new Tree( 1978 ); 10 Person person = new Person( "Bob", "Jones", 1971 ); 2 11 3 12 // create array of IAge references 4 13 IAge[] i. Age. Array = new IAge[ 2 ]; 5 14 6 15 // i. Age. Array[ 0 ] refers to Tree object polymorphically 7 16 i. Age. Array[ 0 ] = tree; 8 17 9 18 // i. Age. Array[ 1 ] refers to Person object polymorphically 10 19 i. Age. Array[ 1 ] = person; 11 20 12 21 // display tree information 13 22 string output = tree + ": " + tree. Name + "n. Age is " + 14 23 tree. Age + "nn"; 15 24 16 25 // display person information 17 26 output += person + ": " + person. Name + "n. Age is: " 18 27 + person. Age + "nn"; 19 28 2002 Prentice Hall. All rights reserved.
29 30 31 32 33 34 35 36 37 38 39 40 // display name and age for each IAge object in i. Age. Array foreach ( IAge age. Reference in i. Age. Array ) { output += age. Reference. Name + ": Age is " + age. Reference. Age + "n"; } Outline Interfaces. Test. c s Message. Box. Show( output, "Demonstrating Polymorphism" ); } // end method Main } // end class Interfaces. Test 57 Use polymorphism to call the Use foreach loop toproperty access of the appropriate class each element of the array Program Output 2002 Prentice Hall. All rights reserved.
1 2 3 4 5 6 7 8 9 10 11 // Fig. 10. 19: IShape. cs [in textbook ed. 1] // Interface IShape for Point, Circle, Cylinder Hierarchy. public interface IShape { // classes that implement IShape must implement these methods // and this property double Area(); double Volume(); Definition of IShape interface string Name { get; } } Outline IShape. cs Classes implementing the interface must define methods Area and Volume (each of which take no arguments and return a double) and a read-only string property Name 2002 Prentice Hall. All rights reserved. 58
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 // Fig. 10. 20: Point 3. cs [in textbook ed. 1] // Point 3 implements interface IShape and represents // an x-y coordinate pair. using System; Outline Point 3. cs // Point 3 implements IShape interface public class Point 3 : IShape { private int x, y; // Point 3 coordinates // default constructor public Point 3() { // implicit call to Object constructor occurs here } // constructor public Point 3( int x. Value, int y. Value ) { X = x. Value; Y = y. Value; } // property X public int X { get { return x; } Class Point 3 implements the IShape interface 2002 Prentice Hall. All rights reserved. 59
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 Outline set { x = value; } Point 3. cs } // property Y public int Y { get { return y; } Implementation of IShape method Area (required), declared virtual to allow deriving classes to override set { y = value; } } // return string representation of Point 3 object public override string To. String() { return "[" + X + ", " + Y + "]"; } // implement interface IShape method Area public virtual double Area() { return 0; } 2002 Prentice Hall. All rights reserved. 60
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 Outline // implement interface IShape method Volume public virtual double Volume() { return 0; } // implement property Name of IShape interface public virtual string Name { get { Implementation of IShape method return "Point 3"; Volume (required), declared virtual } } allow deriving classes to override } // end class Point 3. cs to Implementation of IShape property Name (required), declared virtual to allow deriving classes to override 2002 Prentice Hall. All rights reserved. 61
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 // Fig. 10. 21: Circle 3. cs [in textbook ed. 1] // Circle 3 inherits from class Point 3 and overrides key members. using System; // Circle 3 inherits from class Point 3 public class Circle 3 : Point 3 { private double radius; // Circle 3 radius Outline Circle 3. cs // default constructor public Circle 3() { // implicit call to Point 3 constructor occurs here } // constructor public Circle 3( int x. Value, int y. Value, double radius. Value ) : base( x. Value, y. Value ) { Radius = radius. Value; } // property Radius public double Radius { get { return radius; } Definition of class Circle 3 which inherits from Point 3 2002 Prentice Hall. All rights reserved. 62
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 set { // ensure non-negative Radius value if ( value >= 0 ) radius = value; } Outline Circle 3. cs } // calculate Circle 3 diameter public double Diameter() { return Radius * 2; } Override the Point 3 implementation of Area // calculate Circle 3 circumference public double Circumference() { return Math. PI * Diameter(); } // calculate Circle 3 area public override double Area() { return Math. PI * Math. Pow( Radius, 2 ); } // return string representation of Circle 3 object public override string To. String() { return "Center = " + base. To. String() + "; Radius = " + Radius; } 2002 Prentice Hall. All rights reserved. 63
64 65 66 67 68 69 70 71 72 73 // override property Name from class Point 3 public override string Name { get { return "Circle 3"; } } } // end class Circle 3 Outline Circle 3. cs Override the Point 3 implementation of Name 2002 Prentice Hall. All rights reserved. 64
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 // Fig. 10. 22: Cylinder 3. cs [in textbook ed. 1] // Cylinder 3 inherits from class Circle 2 and overrides key members. using System; // Cylinder 3 inherits from class Circle 3 public class Cylinder 3 : Circle 3 { private double height; // Cylinder 3 height Outline Cylinder 3. cs // default constructor public Cylinder 3() { // implicit call to Circle 3 constructor occurs here } // constructor public Cylinder 3( int x. Value, int y. Value, double radius. Value, double height. Value ) : base( x. Value, y. Value, radius. Value ) { Height = height. Value; } // property Height public double Height { get { return height; } Declaration of class Cylinder 3 which inherits from class Circle 3 2002 Prentice Hall. All rights reserved. 65
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 set { Override the Point 3 // ensure non-negative Height value implementation of Volume if ( value >= 0 ) height = value; Override the Circle 3 } } Outline Cylinder 3. cs implementation of Area // calculate Cylinder 3 area public override double Area() { return 2 * base. Area() + base. Circumference() * Height; } // calculate Cylinder 3 volume public override double Volume() { return base. Area() * Height; } // return string representation of Cylinder 3 object public override string To. String() { return "Center = " + base. To. String() + "; Height = " + Height; } 2002 Prentice Hall. All rights reserved. 66
58 59 60 61 62 63 64 65 66 67 // override property Name from class Circle 3 public override string Name { get { return "Cylinder 3"; } } } // end class Cylinder 3 Outline Cylinder 3. cs Override the Circle 3 implementation of Name 2002 Prentice Hall. All rights reserved. 67
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 Outline // Fig. 10. 23: Interfaces 2 Test. cs [in textbook ed. 1] // Demonstrating polymorphism with interfaces in // Point-Circle-Cylinder hierarchy. using System. Windows. Forms; 68 Create an array of Interfaces 2 Test. IShape references cs (IShape is an Assign an IShape reference interface) to reference a Point 3 object args ) public class Interfaces 2 Test { public static void Main( string[] { // instantiate Point 3, Circle 3 and Cylinder 3 objects Assign an IShape reference Point 3 point = new Point 3( 7, 11 ); Circle 3 circle = new Circle 3( 22, 8, 3. 5 ); to reference a Circle 3 object Cylinder 3 cylinder = new Cylinder 3( 10, 3. 3, 10 ); // create array of IShape references IShape[] array. Of. Shapes = new IShape[ 3 ]; Assign an IShape reference to reference a Cylinder 3 object // array. Of. Shapes[ 0 ] references Point 3 object array. Of. Shapes[ 0 ] = point; // array. Of. Shapes[ 1 ] references Circle 3 object array. Of. Shapes[ 1 ] = circle; // array. Of. Shapes[ 2 ] references Cylinder 3 object array. Of. Shapes[ 2 ] = cylinder; string output = point. Name + ": " + point + "n" + circle. Name + ": " + circle + "n" + cylinder. Name + ": " + cylinder; 2002 Prentice Hall. All rights reserved.
32 33 34 35 36 37 38 39 40 foreach ( IShape shape in array. Of. Shapes ) { output += "nn" + shape. Name + ": n. Area = " + shape. Area() + "n. Volume = " + shape. Volume(); } Outline Interfaces 2 Test. cs Message. Box. Show( output, "Demonstrating Polymorphism" ); } } 69 Use polymorphism to call the appropriate class’s method or property Program Output 2002 Prentice Hall. All rights reserved.
70 [10. 10 in textbook ed. 1] Delegates • Sometimes useful to pass methods as arguments to other methods • Example - sorting: – The same method can be used to sort in the ascending order and in the descending order – The only difference, when comparing elements: • swap them only if the first is larger than the second for ascending order (e. g. , …, 9, 3, … => …, 3, 9, … ) • swap them only if the first is smaller than the second for descending order (e. g. , …, 4, 7, … => …, 7, 4, … ) • C# prohibits passing a method reference directly as an argument to another method. Must use delegates - delegate = a class that encapsulates sets of references to methods – Analogy: Prof. Ninu Atluri requires that students submit homeworks in yellow envelopes She allows a few students to use a single yellow envelope, but does not accept any homeworks not “encapsulated” by an envelope. Prof. Atluri <--> “receiving method” (to which other methods’references are passed) homework <--> method reference (passed to another method) yellow envelope <--> delegate encapsulating references to passed methods 2002 Prentice Hall. All rights reserved. Slide modified by L. Lilien
71 • Delegates must be declared before use • Delegate declaration specifies: • the parameter-list • the return type of the methods the delegate can refer to - E. g. delegate Comparator: public delegate bool Comparator( int element 1, int element 2 ); • Delegates (delegate objects) are sets of references to methods – E. g. , delegate Comparator - a set of references to 2 methods: Sort. Ascending and Sort. Descending 2002 Prentice Hall. All rights reserved. Slide modified by L. Lilien
72 • Methods that can be referred to by a delegate, must have the same signature as the delegate – E. g. : public delegate bool Comparator( int el 1, int el 2 ); signature of Comparator is: (int, int) -> bool – Methods Sort. Ascending or Sort. Descending referred to by Comparator must have the same signature ((int, int) -> bool) private bool Sort. Ascending( int element 1, int element 2 ) private bool Sort. Descending( int element 1, int element 2 ) – Delegate instances can then be created to refer to the methods 2002 Prentice Hall. All rights reserved. Slide modified by L. Lilien
73 • Delegates can be passed to methods – E. g. , delegate Comparator can be passed to method Sort. Array • Once a delegate instance is created (below: instance of delegate Comparator is created with new), the method it refers to (below: Sort. Ascending) can be invoked by the method (below: Sort. Array) to which the delegate passed it – E. g. : Delegate. Bubble. Sort. Array( element. Array, new Delegate. Bubble. Sort. Comparator( Sort. Ascending ) ) • The method to which a delegate passed methods can then invoke the methods the delegate object refers to – E. g. , method Sort. Array can invoke method Sort. Ascending to which delegate object Comparator refers to 2002 Prentice Hall. All rights reserved. Slide modified by L. Lilien
74 • Example – sorting (continued from slide 70) – Declare delegate Comparator : public delegate bool Comparator( int element 1, int element 2 ); // delegate signature: (int, int) -> bool – Use delegate Comparator to pass the appropriate comparison methods (Sort. Ascending or Sort. Descending) to method Sort. Array: • Delegate. Bubble. Sort. Array( element. Array, new Delegate. Bubble. Sort. Comparator( Sort. Ascending ) ) [seen above] • Delegate. Bubble. Sort. Array(element. Array, new Delegate. Bubble. Sort. Comparator( Sort. Descending ) ) [The passed methods (Sort. Ascending and Sort. Descending) have the same signatures ((int, int) -> bool ) as delegate Comparator] 2002 Prentice Hall. All rights reserved. Slide modified by L. Lilien
75 • Types of delegates – singlecast delegate - contains one method • created or derived from class Delegate (from System namespace) – multicast delegate - contains multiple methods • created or derived from class Multicast. Delegate (from System namespace) – E. g. , Comparator is a singlecast delegate • Bec. each instance contains a single method (either Sort. Ascending or Sort. Descending) • Delegates are very useful for event handling – We’ll see how used for mouse click events – Used for event handling - Chapters 12 -14 • Not discussed in CS 1120 2002 Prentice Hall. All rights reserved. Slide modified by L. Lilien
1 2 3 4 5 6 7 8 9 10 • Outline // Fig. 10. 24: Delegate. Bubble. Sort. cs [in textbook ed. 1] // Demonstrating delegates for sorting numbers. 76 public class Delegate. Bubble. Sort Call delegate method to { Delegate. Bubble. So array elements public delegate bool Comparator( intcompare element 1, rt. cs int element 2 ); // Declare delegate Comparator, i. e. , declare // signature for the method. Method swaps the two // No implementation here (no body Swap, for Comparator). arguments (passed by reference) // sort array using Comparator delegate public static void Sort. Array( int[] array, Comparator Compare ) // Reference to delegate Comparator // passed as a parameter to Sort. Array method. { definition for ( int pass = 0; pass < array. Length; Delegate pass++ Comparator ) 12 13 14 15 7 16 8 17 9 order 10 18 11 19 12 20 13 21 14 22 15 23 16 24 17 25 18 26 19 27 20 28 21 29 } for ( int i = 0; i < array. Length - declaration; defines a delegate to a method that takes two 1; i++ ) integer parameters and returns a boolean if ( Compare( array[ i ], array [ i + 1 ] ) ) // if Compare returns true, elements are out of } Swap( ref array[ i ], ref array[ i + 1 ] ); // swap two elements private static void Swap( ref int first. Element, Method Sort. Array which takes an ref int second. Element ) integer array and a Comparator delegate { int hold = first. Element; first. Element = second. Element; second. Element = hold; } Slide modified by L. Lilien 2002 Prentice Hall. All rights reserved.
1 2 3 // Fig. 10. 25: Bubble. Sort. Form. cs [in textbook ed. 1] // Demonstrates bubble sort using delegates to determine // the sort order. // Some thing will be magic for you (e. g. button click handling) using System; using System. Drawing; using System. Collections; using System. Component. Model; using System. Windows. Forms; 4 5 6 7 8 9 10 public class Bubble. Sort. Form : System. Windows. Form 11 { 12 private System. Windows. Forms. Text. Box original. Text. Box; 3 13 private System. Windows. Forms. Text. Box sorted. Text. Box; 4 14 private System. Windows. Forms. Button create. Button; // 3 buttons 5 15 private System. Windows. Forms. Button ascending. Button; 6 16 private System. Windows. Forms. Button descending. Button; 7 17 private System. Windows. Forms. Label original. Label; 8 18 private System. Windows. Forms. Label sorted. Label; 9 19 10 20 private int[] element. Array = new int[ 10 ]; 11 21 12 22 // create randomly generated set of numbers to sort 13 23 private void create. Button_Click( object sender, 14 24 System. Event. Args e ) // magic here 15 25 { 16 26 // clear Text. Boxes 17 27 original. Text. Box. Clear(); 18 28 sorted. Text. Box. Clear(); 19 29 20 30 // create random-number generator 21 31 Random random. Number = new Random(); 22 32 Outline 77 Bubble. Sort. Form. c s Slide modified by L. Lilien 2002 Prentice Hall. All rights reserved.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 • 60 61 62 63 64 } // populate element. Array with random integers for ( int i = 0; i < element. Array. Length; i++ ) { element. Array[ i ] = random. Number. Next( 100 ); original. Text. Box. Text += element. Array[ i ] + "rn"; } Outline 78 Bubble. Sort. Form. cs To sort in ascending order, delegate for the private bool Sort. Ascending( int element 1, int element 2 ) Sort. Ascending method to { method Sort. Array return element 1 > element 2; Method Sort. Descending returns true if } the first argument is smaller then the // sort randomly generated numbers in ascending order returns false otherwise second; // delegate implementation for ascending sort // More precisely: implementation of Sort. Ascending method which can besend a // passed to another method via Comparator delegate (matches its signature) private void ascending. Button_Click( object sender, System. Event. Args e ) // magic here { Method Sort. Ascending returns // sort array, passing delegate for Sort. Ascending Delegate. Bubble. Sort. Array( element. Array, true if the first argument is new Delegate. Bubble. Sort. Comparator( larger then the second; returns Sort. Ascending ) ); } Display. Results(); false otherwise // delegate implementation for desc. sort // More precisely: implementation of Sort. Descending method which can be // passed to another method via Comparator delegate (matches its signature) private bool Sort. Descending( int element 1, int element 2 ) { return element 1 < element 2; } Slide modified by L. Lilien 2002 Prentice Hall. All rights reserved.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 // sort randomly generating numbers in descending order private void descending. Button_Click( object sender, System. Event. Args e ) // magic here { // sort array, passing delegate for Sort. Descending Delegate. Bubble. Sort. Array( element. Array, new Delegate. Bubble. Sort. Comparator( Sort. Descending ) ); } Outline 79 Bubble. Sort. Form. c s Display. Results(); // display the sorted array in sorted. Text. Box private void Display. Results() { sorted. Text. Box. Clear(); } } foreach ( int element in sorted. Text. Box. Text += To sort in descending order, send a element. Array delegate ) to the Sort. Descending element + "rn"; method to method Sort. Array // main entry point for application public static void Main( string[] args ) { Application. Run( new Bubble. Sort. Form() ); // new instance waits for button click } Slide modified by L. Lilien 2002 Prentice Hall. All rights reserved.
Outline 80 Bubble. Sort. Form. c s Program Output 2002 Prentice Hall. All rights reserved.
11. 8. Operator Overloading • C# contains many operators that are defined for some primitive types 81 – E. g. , + - * / • It is often useful to use operators with user-defined types – E. g. , user-defined complex number class with + - * • Operator notation may often be more intuitive then method calls – E. g. , ‘a+b’ more intuitive than ‘Myclass. Add. Integers( a, b )’ • C# allows programmers to overload operators to make them [polymorphically] sensitive to the context in which they are used – Overloading operators is a kind of polymorphism • What looks like the same operator used for different types – E. g. , ‘+’ for primitive type int and ‘+’ for user-defined type Complex. Number – Each time different actions performed – polymorphism at work 2002 Prentice Hall. All rights reserved. Slide modified by L. Lilien
82 • Methods define the actions to be taken for the overloaded operator • They are in the form: public static Return. Type operator-to-be-overloaded( arguments ) – These methods must be declared public and static – The return type is the type returned as the result of evaluating the operation – The keyword operator follows the return type to specify that this method defines an operator overload – The last piece of information is the operator to be overloaded • E. g. , operator ‘+’: public static Comp. Nr operator + ( Comp. Nr x, Int y, Int z ) – If the operator is unary, one argument must be specified, if the operator is binary, then two, etc. • E. g. , operator + shown above is ternary (3 parameters) 2002 Prentice Hall. All rights reserved. Slide modified by L. Lilien
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 // Fig. 10. 26: Complex. Number. cs [in textbook ed. 1] // Class that overloads operators for adding, subtracting // and multiplying complex numbers. public class Complex. Number { private int real; private int imaginary; // default constructor public Complex. Number() {} Outline 83 Complex. Number. cs Property Real provides access to the real part of the complex number // constructor public Complex. Number( int a, int b ) { Real = a; Class Complex. Number Imaginary = b; } definition // return string representation of Complex. Number public override string To. String() { return "( " + real + ( imaginary < 0 ? " - " + ( imaginary * -1 ) : " + imaginary ) + "i )"; // conditional operator (? : ) } // property Real public int Real { get { return real; } Slide modified by L. Lilien 2002 Prentice Hall. All rights reserved.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 Outline set { real = value; } } // end property Real Overload the addition (+) operator for Complex. Numbers. 84 Complex. Number. cs // property Imaginary public int Imaginary { get { return imaginary; } set { imaginary = value; } } // end property Imaginary Property Imaginary provides access to the imaginary part of a complex number // overload the addition operator public static Complex. Number operator + ( Complex. Number x, Complex. Number y ) { return new Complex. Number( x. Real + y. Real, x. Imaginary + y. Imaginary ); } // non-overloaded ‘+’ (for int’s) is used above twice // since x. Real, y. Real, x. Imaginary, y. Imaginary are all // int’s - see Lines 7 -8 & 28 -56 Slide modified by L. Lilien 2002 Prentice Hall. All rights reserved.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 // provide alternative to overloaded + operator // for addition public static Complex. Number Add( Complex. Number x, Complex. Number y ) { return x + y; // overloaded ‘+’ (just. Subtract defined –in lines 59 -64 Method provides an in } // this class) used to add 2 Complex. Numbers x & y Outline 85 Complex. Number. cs alternative to the subtraction operator // overload the subtraction operator public static Complex. Number operator - ( Overloads the multiplication (*) Complex. Number x, Complex. Number y ) operator for Complex. Numbers { return new Complex. Number( x. Real - y. Real, x. Imaginary - y. Imaginary ); } // non-overloaded ‘-’ (for int’s) is used above twice // since x. Real, y. Real, x. Imaginary, y. Imaginary are all // int’s - see Lines 7 -8 & 28 -56 // provide alternative to overloaded - operator // for subtraction public static Complex. Number Subtract( Complex. Number x, Complex. Number y ) { Add in – provides an in this return x - y; // overloaded ‘-’Method (just def. lines 75 -80 } // class) used to subtract Complex. Number from Complex. Number alternative toythe addition operator x // overload the multiplication operator Overload the subtraction (-) public static Complex. Number operator * (operator for Complex. Numbers Complex. Number x, Complex. Number y ) { return new Complex. Number( x. Real * y. Real - x. Imaginary * y. Imaginary, x. Real * y. Imaginary + y. Real * x. Imaginary ); } // non-overloaded ‘*’, ‘-’ and ‘+’ (for int’s) are used above // since x. Real, y. Real, x. Imaginary, y. Imaginary are all // int’s - see Lines 7 -8 & 28 -56 Slide modified by L. Lilien 2002 Prentice Hall. All rights reserved.
98 99 100 101 102 103 104 105 106 107 // provide alternative to overloaded * operator // for multiplication public static Complex. Number Multiply( Complex. Number x, Complex. Number y ) { return x * y; // overloaded ‘*’ (just def. in lines 91 -97 in this } // class) used to multiply 2 Complex. Numbers x & y } // end class Complex. Number Outline 86 Complex. Number. cs Method Multiply – provides an alternative to the multiplication operator Note: 1) Some. NET languages do not support operator overloading. 2) The alternative methods: public static Complex. Number Add ( Complex. Number x, Complex. Number y ) public static Complex. Number Subtract ( Complex. Number x, Complex. Number y ) public static Complex. Number Multiply( Complex. Number x, Complex. Number y ) for adding, subtracting and mutliplying Complex. Numbers, respectively, are needed to ensure that the Complex. Number class can be used in such languages. (of course, it can be used only with ‘Complex. Number Add ( x, y )’, not ‘x + y’, etc. ) 3) We do not use the alternative methods in our test below. Slide modified by L. Lilien 2002 Prentice Hall. All rights reserved.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 // Fig 10. 27: Operator. Overloading. cs [in textbook ed. 1] // An example that uses operator overloading using using System; System. Drawing; System. Collections; System. Component. Model; System. Windows. Forms; System. Data; Outline Operator. Overload ing. cs public class Complex. Test : System. Windows. Form { private System. Windows. Forms. Label real. Label; private System. Windows. Forms. Label imaginary. Label; private System. Windows. Forms. Label status. Label; private System. Windows. Forms. Text. Box real. Text. Box; private System. Windows. Forms. Text. Box imaginary. Text. Box; private private System. Windows. Forms. Button 87 first. Button; second. Button; add. Button; subtract. Button; multiply. Button; private Complex. Number x = new Complex. Number(); private Complex. Number y = new Complex. Number(); [STAThread] static void Main() { Application. Run( new Complex. Test() ); } 2002 Prentice Hall. All rights reserved.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 private void first. Button_Click( object sender, System. Event. Args e ) { x. Real = Int 32. Parse( real. Text. Box. Text ); x. Imaginary = Int 32. Parse( imaginary. Text. Box. Text ); real. Text. Box. Clear(); imaginary. Text. Box. Clear(); status. Label. Text = "First Complex Number is: " + x; } Outline 88 Operator. Overload ing. cs Use overloaded addition operator to add two Complex. Numbers private void second. Button_Click( object sender, System. Event. Args e ) { y. Real = Int 32. Parse( real. Text. Box. Text ); y. Imaginary = Int 32. Parse( imaginary. Text. Box. Text ); real. Text. Box. Clear(); imaginary. Text. Box. Clear(); Use overloaded subtraction operator status. Label. Text = "Second Complex Number is: " + y; to subtract two Complex. Numbers } // add complex numbers private void add. Button_Click( object sender, System. Event. Args e ) { status. Label. Text = x + " + y + " = " + ( x + y ); } // subtract complex numbers private void subtract. Button_Click( object sender, System. Event. Args e ) { status. Label. Text = x + " - " + y + " = " + ( x - y ); } 2002 Prentice Hall. All rights reserved.
68 69 70 71 72 73 74 75 // multiply complex numbers private void multiply. Button_Click( object sender, System. Event. Args e ) { status. Label. Text = x + " * " + y + " = " + ( x * y ); } } // end class Complex. Test Outline 89 Operator. Overload ing. cs Use overloaded multiplication operator to multiply two Complex. Numbers Program Output 2002 Prentice Hall. All rights reserved.
Outline 90 Operator. Overload ing. cs Program Output 2002 Prentice Hall. All rights reserved.
91 The End 2002 Prentice Hall. All rights reserved.
- Slides: 91