Ch 10- Advanced Object-Oriented Programming Features Una Donnelly
We Will Learn: Using Inheritance Dynamic Link Library (DLL) Abstract, Partial, and Generic Classes Polymorphic Programming
Inheritance Create a general class → specialized classes with access to members of general class General class = Base class Override Method to change it in a certain specialized class: Public override string ToString() {return firstName + “ “ + lastName;} class: Person Public Name, age, etc. Specialized class: Student Private Student ID, year Specialized class: Worker Private Title, Company
Inheritance: Derived Classes public class Person { protected string name = "John Smith"; public virtual void GetInfo() { Console.WriteLine("Name: {0}", name); Console.WriteLine("SSN: {0}", ssn); } } class Employee : Person { public string id = "ABC567EFG"; public override void GetInfo() { // Calling the base class GetInfo method: base.GetInfo(); Console.WriteLine("Employee ID: {0}", id); } } Base class is identified Can be referenced in a method or arguments
DLL Any application can reference a class if it is stored in DLL Select the Class Library Template To use DLL in an application add using statement to top of code: using <Namespace of MyClass>;
Abstract Classes Add abstract modifier to stop other classes from instantiating base class objects May specify common methods w/out defining implementation Name: public abstract class A Cannot be used; Only derived from
Compiled to Single Class Partial Classes A class split into two files For example: Windows Forms Useful for sharing work All files must use partial keyword All modifier (public/private) must match Developer 1: Class1.cs Compile Compiled to Single Class Developer 2: Class2.cs
Generic Classes Generics provide the solution to a limitation in earlier versions of the common language runtime and the C# language in which generalization is accomplished by casting types to and from the universal base type Object. By creating a generic class, you can create a collection that is type-safe at compile-time. Encapsulate operations that are not specific to a particular data type No need to alter code for each data type Identify where method implementations will change and put in placeholder Prototype that gives the function but not how it will be implemented Starting with an existing concrete class, and changing types into type parameters one at a time
Generic Classes: Sample Code class BaseNode { } class BaseNodeGeneric<T> { } // concrete type class NodeConcrete<T> : BaseNode { } //closed constructed type class NodeClosed<T> : BaseNodeGeneric<int> { } //open constructed type class NodeOpen<T> : BaseNodeGeneric<T> { } Generic classes that inherit from open constructed types must supply type arguments for any base class type parameters that are not shared by the inheriting class: Class BaseNodeMultiple<T, U> { } //No error class Node4<T> : BaseNodeMultiple<T, int> { } //No error class Node5<T, U> : BaseNodeMultiple<T, U> { } //Generates an error //class Node6<T> : BaseNodeMultiple<T, U> {} ← Closed-Parameter Specified ← Open-Parameter not Specified
Polymorphism Polymorphism means "many-shaped" and it has two distinct aspects Objects of a derived class may be treated as objects of a base class at runtime e.g. method parameters Derived classes can override the virtual methods of the base class - thus at runtime you can call the method on the base class and invoke the method of the derived class Virtual methods enable you to work with groups of related objects in a uniform way
Polymorphism: Sample Code public class Shape { // A few example members public int X { get; private set; } public int Y { get; private set; } public int Height { get; set; } public int Width { get; set; } // Virtual method public virtual void Draw() { Console.WriteLine("Performing base class drawing tasks"); } } class Circle : Shape { public override void Draw() { // Code to draw a circle... Console.WriteLine("Drawing a circle"); base.Draw(); } } class Rectangle : Shape { public override void Draw() { // Code to draw a rectangle... Console.WriteLine("Drawing a rectangle"); base.Draw(); } } class Triangle : Shape { public override void Draw() { // Code to draw a triangle... Console.WriteLine("Drawing a triangle"); base.Draw(); } } class Program { static void Main(string[] args) { // Polymorphism part #1: Rectangle, Triangle and Circle // can all be used where ever a Shape is expected. No cast // required because an implicit conversion exists from a // derived class to its base class. System.Collections.Generic.List<Shape> shapes = new System.Collections.Generic.List<Shape>(); shapes.Add(new Rectangle()); shapes.Add(new Triangle()); shapes.Add(new Circle()); // Polymorphism part #2: the virtual method Draw is invoked // on each of the derived classes, not the base class. foreach (Shape s in shapes) { s.Draw(); } // Keep the console open in debug mode. Console.WriteLine("Press any key to exit."); Console.ReadKey(); } } /* Output: Drawing a rectangle Performing base class drawing tasks Drawing a triangle Performing base class drawing tasks Drawing a circle Performing base class drawing tasks */