1 / 36

Introduction

Introduction. Polymorphism allows programmers to develop: Programs that handle a wide variety of related classes in a generic manner Systems that are easily extensible and maintainable. Derived-Class-Object to Base-Class-Object Conversion. Class hierarchies

heller
Télécharger la présentation

Introduction

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Introduction Polymorphism allows programmers to develop: • Programs that handle a wide variety of related classes in a generic manner • Systems that are easily extensible and maintainable

  2. Derived-Class-Object to Base-Class-Object Conversion • Class hierarchies • Can assign derived-class objects to base-class references (eg. circle = cylinder;) • Can explicitly cast between types in a class hierarchy (eg. cylinder = (Cylinder) circle;) as long as circle references a cylinder object or an object of a derived class of cylinder (eg. pipe object) • An object of a derived-class can be treated as an object of its base-class • Good use: 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

  3. Create a Point object Assign a Point reference to reference a Circle object Create a Circle object Use base-class reference to access a derived-class object Assign a Circle reference to reference a Point object (downcast) Use derived-class reference to access a base-class object 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 object 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" );

  4. Test if point1 references a Circle object – it does not // 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" );

  5. Comments • With virtual method, such as ToString – the version called depends on type of object, not type of reference. • Assigning a base-class object (or a base-class reference) to a derived-class reference (without an explicit cast) is a syntax error. • If an invalid cast is attempted, C# throws an InvalidCastException • The is keyword enables a program to determine whether a cast operation would be successful.

  6. Types and switch Statements • Using switch to determine the type of an object • Distinguish between object, perform appropriate action depending on object type • Potential problems using switch • Forgetting to include a type test or testing all possible cases • Forgetting to modify all relevant switch structures, when new types are added • Every addition or deletion of a class requires modification of every switch statement in the system; • C#’s polymorphic mechanism performs the equivalent logic, eliminating unnecessary switch logic.

  7. Polymorphism Examples • SpaceObject base-class – contains method DrawYourself • Martian derived-class (implements DrawYourself) • Venutian derived-class (implements DrawYourself) • Plutonian derived-class (implements DrawYourself) • SpaceShip derived-class (implements DrawYourself) • A screen-manager program may contain a SpaceObject array of references to objects of various classes that derive from SpaceObject • To refresh the screen, the screen-manager calls DrawYourself on each object in the array • The program polymorphically calls the appropriate version of DrawYourself on each object, based on the type of that object

  8. Polymorphism Example SpaceObject [] spaceobjects = new SpaceObject [10]; //use switch to construct each object… switch (inputCH ) { case ‘V’: spaceobjects[i] = new Venuetian( ); break; . : } //now process them – no need for switch foreach (s in spaceobjects) s.DrawYourself();

  9. 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

  10. Abstract Classes and Methods • Abstract classes are used to provide appropriate base classes from which other (concrete) classes may inherit • Abstract base classes are too generic to define 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

  11. Abstract Classes and Methods • Any class with an abstract method or property must be declared abstract • Concrete classes use the keyword override to provide implementations for all the abstract methods and properties of the base-class • 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

  12. 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

  13. Declaration of virtual methods Area and Volume with default implementations Declaration of abstract class Shape Declaration of read-only abstract property Name; implementing classes will have to provide an implementation for this property publicabstractclass Shape { // return Shape's area publicvirtualdouble Area() { return0; } // return Shape's volume publicvirtualdouble Volume() { return0; } // return Shape's name publicabstractstring Name { get; } }

  14. Point2’s implementation of the read-only Name property Class Point2 inherits from class Shape // Point2 inherits from abstract class Shape publicclass Point2 : Shape { privateint x, y; // Point2 coordinates // implement abstract property Name of class Shape publicoverridestring Name { get { return"Point2"; } } Point2.cs

  15. Override the Area method (defined in class Shape) Override the read-only Name property Definition of class Circle2 which inherits from class Point2 // Circle2 inherits from class Point2 publicclass Circle2 : Point2 { privatedouble radius; // Circle2 radius // calculate Circle2 area publicoverridedouble Area() { returnMath.PI * Math.Pow( Radius, 2 ); } // override property Name from class Point2 publicoverridestring Name { get { return"Circle2"; } }

  16. Class Cylinder2 derives from Circle2 // Cylinder2 inherits from class Circle2 publicclass Cylinder2 : Circle2 { privatedouble height; // Cylinder2 height // default constructor public Cylinder2() { // implicit call to Circle2 constructor occurs here } // constructor public Cylinder2( intxValue, intyValue, doubleradiusValue, doubleheightValue ) : base( xValue, yValue, radiusValue ) { Height = heightValue; } // property Height publicdouble Height { get { return height; } set {// ensure non-negative height value if ( value >= 0 ) height = value; } } Cylinder2.cs

  17. Override read-only property Name Override Area implementation of class Circle2 Override Volume implementation of class Shape // calculate Cylinder2 area publicoverridedouble Area() { return2 * base.Area() + base.Circumference() * Height; } // calculate Cylinder2 volume publicoverridedouble Volume() { returnbase.Area() * Height; } // return string representation of Circle2 object publicoverridestring ToString() { returnbase.ToString() + "; Height = " + Height; } // override property Name from class Circle2 publicoverridestring Name { get { return"Cylinder2"; } } } // end class Cylinder2 Cylinder2.cs

  18. Create an array of Shape objects Assign a Shape reference to reference a Point2 object Assign a Shape reference to reference a Circle2 object Assign a Shape reference to reference a Cylinder2 object // Demonstrates polymorphism in Point-Circle-Cylinder hierarchy. publicpartialclassAbstractShapesForm : Form { public AbstractShapesForm() { InitializeComponent(); // instantiate Point2, Circle2 and Cylinder2 objects Point2 point = new Point2( 7, 11 ); Circle2 circle = new Circle2( 22, 8, 3.5 ); Cylinder2 cylinder = new Cylinder2( 10, 10, 3.3, 10 ); // create empty array of Shape base-class references Shape[] arrayOfShapes = new Shape[ 3 ]; // arrayOfShapes[ 0 ] refers to Point2 object arrayOfShapes[ 0 ] = point; // arrayOfShapes[ 1 ] refers to Circle2 object arrayOfShapes[ 1 ] = circle; // arrayOfShapes[ 1 ] refers to Cylinder2 object arrayOfShapes[ 2 ] = cylinder; string output = point.Name + ": " + point + "\n" + circle.Name + ": " + circle + "\n" + cylinder.Name + ": " + cylinder;

  19. Use a foreach loop to access every element of the array // display Name, Area and Volume for each object // in arrayOfShapes polymorphically foreach( Shape shape in arrayOfShapes ) { output += "\n\n" + shape.Name + ": " + shape + "\nArea = " + shape.Area().ToString( "F" ) + "\nVolume = " + shape.Volume().ToString( "F" ); } outputLabel.Text = output; } } Rely on polymorphism to call appropriate version of methods

  20. sealed Classes and Methods • sealed is a keyword in C# • sealed methods cannot be overridden in a derived class • Methods that are declared static and private, are implicitly sealed • 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

  21. Case Study: Creating and Using Interfaces • Interfaces specify the public services (methods and properties) that classes must implement • Interfaces provide no default implementations (i.e., no instance variables and no default-method 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

  22. Case Study: Creating and Using Interfaces • Interfaces are defined using keyword interface • Use inheritance notation to specify a class implements an interface (ClassName : InterfaceName) • Classes may implement more then 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 • Example: interface IShape that specifies methods Area and Volume and property Name. • Example: interface IAge that returns information about an object’s age • Can be used by classes for people, cars, trees (all have an age)

  23. Definition of interface IAge Classes implementing this interface will have to define read-only properties Age and Name // Interface IAge declares property for setting and getting age. publicinterface IAge { int Age { get; } string Name { get; } }

  24. Class Person implements the IAge interface Definition of Age property (required) publicclass Person : IAge { privatestring firstName; privatestring lastName; privateint yearBorn; // constructor public Person( string firstNameValue, string lastNameValue, int yearBornValue ) { firstName = firstNameValue; lastName = lastNameValue; if ( yearBornValue > 0 && yearBornValue <= DateTime.Now.Year ) yearBorn = yearBornValue; else yearBorn = DateTime.Now.Year; } // property Age implementation of interface IAge publicint Age { get { return DateTime.Now.Year - yearBorn; } }

  25. Definition of Name property (required) // property Name implementation of interface IAge publicstring Name { get { return firstName + " " + lastName; }

  26. Implementation of Age property ( required) Class Tree implements the IAge interface // Class Tree contains number of rings corresponding to its age. publicclass Tree : IAge { privateint rings; // number of rings in tree trunk // constructor public Tree( int yearPlanted ) { // count number of rings in Tree rings = DateTime.Now.Year - yearPlanted; } // increment rings publicvoid AddRing() { rings++; } // property Age implementation of interface IAge publicint Age { get { return rings; } }

  27. Definition of Name property (required) // property Name implementation of interface IAge publicstring Name { get { return"Tree"; } } } // end class Tree Tree.cs

  28. Create array of IAge references Assign an IAge reference to reference a Tree object Assign an IAge reference to reference a Person object publicclass InterfacesTest { publicstaticvoid Main( string[] args ) { Tree tree = new Tree( 1978 ); Person person = new Person( "Bob", "Jones", 1971 ); // create array of IAge references IAge[] iAgeArray = new IAge[ 2 ]; // iAgeArray[ 0 ] refers to Tree object polymorphically iAgeArray[ 0 ] = tree; // iAgeArray[ 1 ] refers to Person object polymorphically iAgeArray[ 1 ] = person; // display tree information string output = tree + ": " + tree.Name + "\nAge is " + tree.Age + "\n\n"; // display person information output += person + ": " + person.Name + "\nAge is: " + person.Age + "\n\n"; InterfacesTest.cs

  29. Use polymorphism to call the property of the appropriate class Use foreach loop to access each element of the array // display name and age for each IAge object in iAgeArray foreach ( IAge ageReference in iAgeArray ) { output += ageReference.Name + ": Age is " + ageReference.Age + "\n"; } MessageBox.Show( output, "Demonstrating Polymorphism" ); } // end method Main } // end class InterfacesTest

  30. Delegates • Sometimes useful to pass methods as arguments to other methods • C# does not allow passing of method references directly as arguments, but does provide delegates • Delegates are sets of references to methods • Delegate objects can be passed to methods; methods can then invoke the methods the delegate objects refer to • Delegates that contain one method are known as singlecast delegates and are created or derived from class Delegate • Delegates that contain multiple methods are known as multicast delegates and are created or derived from class MulticastDelegate

  31. Operator Overloading • C# contains many operators (such as + and - ) that are defined for some primitive types • It is often useful to use operators with user-defined types (e.g., a complex number class) • Operator notation may often be more intuitive then method calls • As in C++, C# allows programmers to overload operators to make them sensitive to the context in which they are used

  32. Operator Overloading • Methods define the actions to be taken for the overloaded operator • They are in the form: publicstaticReturnTypeoperatoroperator-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 (such as +, -, *, etc.) • If the operator is unary, one argument must be specified, if the operator is binary, then two, etc.

  33. Overload the addition (+) operator for ComplexNumbers. Class ComplexNumber definition Method Add – provides an alternative to the addition operator publicclass ComplexNumber { privateint real; privateint imaginary; // overload the addition operator publicstatic ComplexNumber operator + ( ComplexNumber x, ComplexNumber y ) { returnnew ComplexNumber( x.Real + y.Real, x.Imaginary + y.Imaginary ); } // provide alternative to overloaded + operatorfor addition publicstatic ComplexNumber Add( ComplexNumber x, ComplexNumber y ) { return x + y; }

  34. Overload the subtraction (-) operator for ComplexNumbers Method Subtract – provides an alternative to the subtraction operator Overloads the multiplication (*) operator for ComplexNumbers // overload the subtraction operator publicstatic ComplexNumber operator - ( ComplexNumber x, ComplexNumber y ) { returnnew ComplexNumber( x.Real - y.Real, x.Imaginary - y.Imaginary ); } // provide alternative to overloaded - operator // for subtraction publicstatic ComplexNumber Subtract( ComplexNumber x, ComplexNumber y ) { return x - y; } // overload the multiplication operator publicstatic ComplexNumber operator * ( ComplexNumber x, ComplexNumber y ) { returnnew ComplexNumber( x.Real * y.Real - x.Imaginary * y.Imaginary, x.Real * y.Imaginary + y.Real * x.Imaginary ); } // provide alternative to overloaded * operator // for multiplication publicstatic ComplexNumber Multiply( ComplexNumber x, ComplexNumber y ) { return x * y; } ComplexNumber.cs

  35. Use addition operator to add two ComplexNumbers Use subtraction operator to subtract two ComplexNumbers Use multiplication operator to multiply two ComplexNumbers publicclass ComplexTest : Form { private ComplexNumber x = new ComplexNumber(); private ComplexNumber y = new ComplexNumber(); // add complex numbers privatevoid addButton_Click( object sender, System.EventArgs e ) { statusLabel.Text = x + " + " + y + " = " + ( x + y ); } // subtract complex numbers privatevoid subtractButton_Click( object sender, System.EventArgs e ) { statusLabel.Text = x + " - " + y + " = " + ( x - y ); } // multiply complex numbers privatevoid multiplyButton_Click( object sender, System.EventArgs e ) { statusLabel.Text = x + " * " + y + " = " + ( x * y ); }

More Related