Advanced Object-Oriented Programming Features 11 C# Programming: From Problem Analysis to Program Design 4th Edition C# Programming: From Problem Analysis to Program Design
Chapter Objectives Learn the major features of object-oriented languages Design and develop multitier applications using component-based development methods Use inheritance to extend the functionality of user-defined classes Create abstract classes that include abstract methods
Chapter Objectives (continued) Distinguish the differences between sealed and abstract classes Become aware of partial classes Design and implement interfaces Understand why polymorphic programming is a common goal in .NET Explore generics and learn how to create generic classes and generic methods
Chapter Objectives (continued) Investigate static versus dynamic typing and become aware of when dynamic and var types are used Work through a programming example that illustrates the chapter’s concepts C# Programming: From Problem Analysis to Program Design
Object-Oriented Language Features Abstraction Generalizing, identifying essential features, hiding nonessential complexities Encapsulation Packaging data and behaviors into a single unit, hiding implementation details Inheritance Extending program units to enable reuse of code Polymorphism Providing multiple (different) implementations of same named behaviors (Overloading)
Component-Based Development Figure 11-1 Component-based development
Component-Based Development (continued) Component-based applications associated with multitier applications – (different layers) Business layer(s) – classes that perform processing Provide functionality for specific system; provide necessary processing Data access layer - classes for accessing data from text files and databases Presentation layer - User interface tier for user interaction Graphical User Interface such as Windows or Web
Component-Based Development (continued) Components facilitates reuse-based approach Define and implement independent components into systems Components are implemented through classes Takes the form of objects or collection of objects Components can then be packaged with different components and used for other applications Classes can be created that extend functionality of original classes C# Programming: From Problem Analysis to Program Design
Inheritance Enables you to: Associated with an "is a" relationship Create a general class and then define specialized classes that have access to the members of the general class (Person→Student →Graduate) Associated with an "is a" relationship Specialized class “is a” form of the general class (Graduate is-a Student) Classes can also have a "has a" relationship, not associated with inheritance "has a" relationship is associated with containment or aggregation (e.g. Student has-a Schedule)
Inheriting from the Object Class Every object inherits four methods as long as reference to the System namespace included Figure 11-2 Methods inherited from an object
Inheriting from Other .NET FCL Classes Experienced inheritance when you developed Windows-based programs Form you created inherited characteristics from System.Windows.Forms.Form class Already had title bar, close, and minimize buttons Add functionality to your programs with minimal programming Extend System.Windows.Forms.Form class to build GUIs (Button, Label, TextBox, ListBox, ImageBox,…) C# Programming: From Problem Analysis to Program Design
Inheriting from Other .NET FCL Classes Base class Derived class Figure 11-3 Derived class Class listed after the colon is the base class. It already has some functionality Class to the left, PresentationGUI, is a derived class Derived class is the new class, the user-defined class C# Programming: From Problem Analysis to Program Design
Creating Base Classes for Inheritance Can define your own classes from which other classes can inherit Base class is called the super or parent class In general, the base class has Data members defined with a private access modifier Constructors defined with public access modifiers Properties offering public access to data fields C# Programming: From Problem Analysis to Program Design
Class Diagram: Person - Student Base class Sub-class (Derived)
Person Class (Base) 1 of 2 1 2 class Person { //data members private string lastName = "n.a"; private string firstName= "n.a"; private int age = 0; private string occupation = "n.a"; //Properties // Verbose style - Property for last name public string LastName get return lastName; } set lastName = value; // Properties –using C# 7.0 style- Expression Bodied Method notation public string FirstName { get => firstName; set => firstName = value; } public int Age { get { return age; } set => age = Math.Abs(value); } public string Occupation { get { return occupation; } set => occupation = value; } 1 2
Person Class (Base) 2 of 2 3 4 5 // Constructor with zero arguments public Person() { } // Constructor with four arguments public Person( string lNameValue, string fNameValue, int ageValue) { LastName = lNameValue; FirstName = fNameValue; Age = ageValue; } //user-defined methods (new formatting feature C# 7.0) public override string ToString() return string.Format( $"Person [ " + $"First= {FirstName} Last= {LastName} " + $"Age= {age} " + $"Ocuppation= {Occupation} ]"); //a virtual method could be overridden by its derived sub-classes public virtual int GetSleepAmount() return 8; 3 4 5
Student Class (Derived/Sub class) 1 of 2 6 class Student : Person { //data members private string major = "not declared yet"; private double gpa = 0.0; private int studentId = 0; //properties (bodied expressions) public string Major { get => major; set => major = value; } public double Gpa { get => gpa; set => gpa = value; } public int StudentId { get=> studentId; set=> studentId = value; } //constructors public Student() :base() { } public Student(string lNameValue,string fNameValue, int ageValue, int idValue, string majorValue, double gpaValue) :base(lNameValue, fNameValue, ageValue) StudentId = idValue; Major = majorValue; Gpa = gpaValue; } 7 8 9
Student Class (Derived/Sub class) 2 of 2 //user-defined methods public override string ToString() { return string.Format( $"\nStudent [ ID= {StudentId} Major= {Major} GPA= {Gpa}" + $"\n\t" + base.ToString() + $" ]"); } public override int GetSleepAmount() //return base.GetSleepAmount(); return 6; 10 11
Access Modifiers Class members defined with private access are restricted to members of the current class Data members are typically defined with private access modifier Private access enables class to protect its data and only allow access to the data through its methods or properties Constructors use public access modifier If they are not public, you would not be able to instantiate objects of the class in other classes Constructors are methods named as the class and have no return type Ancestor private... protected… public… Subclass Only ancestor's public & protected members are visible
Creating Base Classes for Inheritance class Person { //data members private string lastName = "n.a"; private string firstName= "n.a"; private int age = 0; private string occupation = "n.a"; Base class All derived classes will include these four attributes 1 All data members are customarily defined private. Good practice! These default values could be used by zero-args constructor
Properties (Verbose Style) Classic verbose style // Property for last name public string LastName { get return lastName; } set lastName = value; Properties are defined with public access. They provide access to private data and enforcing of 'bussines rules'. No need to declare value. It is used, almost like magic… value refers to the argument sent through an assignment statement get, set and value are contextual keywords 2 Private data member RHS of an assignment
Properties (Compressed notation) In C# Version 7 there is support for a compact notation called EXPRESSION BODIED METHOD that employs the => operator (not to be mistaken with Lambda expressions). The new notation could be used Properties, Constructors, and Destructors (~Person() =>...) //Properties (using Expression Bodied Method's notation) public string Occupation { get => occupation; set => occupation = value; } public string LastName { get=> lastName; set=> lastName = value; } public string FirstName { get => firstName; set => firstName = value; } public int Age { get { return age; } set => age = Math.Abs(value); } 2
Public Access Modifier Properties should offer public access to data fields Properties look like data fields, but are implemented as methods Properties implement the getters (accessors) and setters (mutators) for the class You can make properties be read-only by NOT defining the “set” GOOD PRACTICE. Properties often carry the same name as their associated data member. However, properties use Pascal case (start with capital letter). For example: LastName → lastName Property field/data member
Creating Base Classes for Inheritance: Constructors // Constructor with zero arguments public Person( ) { } // Constructor with four arguments public Person (string lnameValue,string fnameValue, int ageValue) LastName = lnameValue; FirstName = fnameValue; Age = ageValue; All the object's data-members will used their already declared default values 3 Notice, constructor is a method, has same name as class (Person), has no return type, and is overloaded Properties
Overriding Methods Person class example has two additional methods public override string ToString( ) // Defined in Person public virtual int GetSleepAmt( ) // Defined in Person You can replace a method originally defined at a higher level with a new definition Use keyword override in method heading whenever the derived class wants to provide a new definition In order to be a method that can be overridden, keywords virtual, abstract, or override must be part of the heading for the parent class ANCESTOR Method's modifier: virtual, abstract, override DERIVED CLASS override
Base class ToString( ) method Overriding Methods Base class ToString( ) method The Person class example overrides ToString() //using string interpolation - new C# 6.0 formatting feature public override string ToString() { return string.Format( $"\nPerson [ ID= {IdNumber} Age= {age} " + $"First= {FirstName} Last= {LastName} " + $"Ocuppation= {Occupation} ]"); } 4 NOTE: Remember, each class derives from the Object super-class. Therefore, although Person is the Base class in our example, it could be considered a subclass as it derives from Object.
Virtual Methods (continued) A virtual method is one that could be modified by any descendant in its hierarchy. This behavior is in contrast with abstract methods that must be overridden by derived subclasses. //a virtual method could be overridden by its derived sub-classes public virtual int GetSleepAmount() { return 8; } 5 Comment: In our example, the base class sets eight hours of sleep for a Person object. A descendant of Person, say HeavyCoffeeDrinker may require less rest and establishes a different value (4 is enough!).
Virtual Methods (continued) ToString( ) uses the virtual modifier in the Object super class, implying that any derived class can override it ToString( ) method can have many different implementations Example of polymorphism Overriding differs from overloading a method Overridden methods have exactly the same signature Overloaded methods each have a different signature
Creating Derived Classes Derived classes inherit from a base class Derived classes also called subclasses or child classes Derived classes do not have access to data members defined with private access in the parent or base class Derived classes have access to data members defined with protected (and public) access in the parent or base class C# Programming: From Problem Analysis to Program Design
Derived Classes 6 Reference to base class class Student : Person { //data members private string major = "not declared yet"; private double gpa = 0.0; private int studentId = 0; //properties (bodied expressions) ... //constructors public Student() :base() { } Additional subclass data members 6 Indicates which base class constructor to use C# Programming: From Problem Analysis to Program Design
Calling the Base Constructor To call the constructor for the base class, add keyword :base between the constructor heading for the subclass and the opening curly brace //all-arguments constructor public Student(string fnameValue, string lnameValue, int ageValue, string majValue, string studentIdValue) : base(lnameValue, fnameValue, ageValue) // calling base constructor { Major = majValue; StudentId = studentIdValue; } Base constructor must have a constructor with matching signature 9 Use base constructor to create a Person object
Calling the Base Constructor (cont) Student s2 = new Student("Parker", "Peter", 21, 2001234, "CHEM", 4.0); First three arguments, "Parker", "Peter" and 21, are sent to the constructor for Person class which requires first name, last and age. Last three arguments (2001234, "CHEM" 4.0) are used by the Student class constructor to fill up the additional data memebers affiliated to the derived Student class. Student anotherStudent = new Student(); Both, Person and Student default zero-arguments constructors are called when new Student() is invoked.
Calling Overridden Methods of the Base Class Scope Methods defined in subclass take precedence when named the same name as member of a parent class Use keyword base before the method name to call an overridden method of the base class return base.GetSleepAmt( ) // Calls GetSleepAmt( ) in // parent class C# Programming: From Problem Analysis to Program Design
Relationship between the Person and Student Classes Figure 11-5 Inheritance class diagram
Relationship between the Person and Student Classes Figure 11-5 Inheritance class diagram
Abstract Classes Abstract classes are created solely for the purpose of inheritance You need to identify and pull out common characteristics that all objects of that type possess Provide a common definition of a base class so that multiple derived classes can share that definition For example, Person → Student, Faculty Person could be defined as a base abstract class Student defined as derived concrete subclass
Abstract Classes Add keyword abstract on class heading [access modifier] abstract class ClassIdentifier { } // base class In our running example, add abstract to heading of Person base class public abstract class Person ...
Abstract Classes Abstract classes prohibit other classes from instantiating objects based on the abstract class If Person is made abstract, then new Person() would be an invalid call. Can create subclasses (derived classes) of the abstract class Derived classes inherit characteristics from base abstract class Objects can only be created using classes derived from the abstract class (new Student() would be a valid call)
Abstract Methods Consider them as a contract that details what methods must be implemented be derived classes. Abstract methods have no body Implementation details of the method are left up to classes derived from the base abstract class Only permitted in abstract classes Every class that derives from the abstract class must provide implementation details for all abstract methods
Abstract Methods (continued) No additional special keywords are used when a new class is defined to inherit from the abstract base class [access modifier] abstract returnType MethodIdentifier ([parameter list]) ; // No { } included Declaration for abstract method ends with semicolon; NO method body or curly braces Syntax error if you use the keyword static or virtual when defining an abstract method
Abstract Methods (continued) Assume Person has been declared an abstract class. Assume Person includes the following method declaration public abstract void SetHobby(string activityValue); Defined in Person In the derived Student class, you must include an overridden version of the SetHobby method. For instance, public override void SetHobby(string activityValue) { //assume List<string> listHobbies has been added to data members listHobbies.Add(activityValue); } Defined in Student
Sealed Classes A Sealed class cannot be a base class Sealed classes are defined to prevent derivation Objects can be instantiated from the class, but subclasses cannot be derived from it public sealed class Student In this case it would not be possible to create public class UndergraduateStudent : Student
Sealed Methods If you do not want subclasses to be able to provide new implementation details, add the keyword sealed Helpful when a method has been defined as virtual in a base class Don’t seal a method unless that method is itself an override of another method in some base class Assume Person defines the method public virtual void RaiseSalary(double incrementValue) {...} Derived class Student could implement public sealed override void RaiseSalary(double incrementValue) {...} Observe that no subclass of Student could override the method.
Partial Classes Break class up into two or more files Each file uses partial class designation public abstract partial class Person At compile time, the files are merged together All the files must use the partial keyword All of the partial class definitions must be defined in the same assembly (.exe or .dll file) Class name and accessibility modifiers, such as private or public, must also match
Interfaces C# supports single inheritance Classes can implement any number of interfaces Only inherit from a single class, abstract or non-abstract Think of an interface as a class that is totally abstract; all methods are abstract Interfaces are contracts that mandate you what needs to be implemented Abstract classes can have abstract and regular methods Classes implementing interface agree to define details for all of the interface’s methods
Using .NET Interfaces A useful .NET interface that you may consider using is called Icomparable. It allows you to define how two objects could be compared. The interface has only one method called CompareTo() The integer result returned by CompareTo(Object other) when matching this object with the other object are numbers as follows ZERO if this object is equal to other object POSITIVE if this object is greater than other object NEGATIVE if this object < other object
Using .NET Interfaces Assume Person is declared as follows public class Person : IComparable<Person> Assume Person includes the following method public virtual int CompareTo(Person other) { if (this.age == other.age) return 0; else if (this.age > other.age) return 1; else return -1; } Observe that the criteria for comparison is arbitrary. In this case we have chosen age to compare two Person objects.
Using .NET Interfaces Assume a test class has already defined two instances of Person identified as p1 and p2 respectively. Person p1 = new Person("Prince", "Diane", 22); Person p2 = new Person(); To compare both objects, one may say if (p1.CompareTo(p2)!=0) { Console.WriteLine("Different people!"); } In this case, the output would be "Different people!"
Polymorphism Ability for classes to provide different implementations details for methods with same name Determines which method to call or invoke at run time based on which object calls the method (Dynamic binding) Example…ToString( ) method Through inheritance, polymorphism is made possible by allowing classes to override base class members
Generics … Reduce the need to rewrite algorithms for each data type Create generic classes, delegates, interfaces, and methods Identify where data will change in the code segment by putting a placeholder in the code for the type parameters public class Stack<T> { private T[] items; private int stackPointer = 0; public Stack(int size) items = new T[size]; } … Generic Stack class
Generic Classes (continued) public T Pop( ) { return items[--stackPointer]; } public void Push(T anItem) items[stackPointer] = anItem; stackPointer++;
Generic Methods Similar to defining a generic class Can define generic methods that are not part of generic classes Insert identifier between left and right brackets on the method definition line to indicate it is a generic method Then place that identifier either in the parameter list or as a return type or in both places
Generic Methods (continued) public void SwapData <T> (ref T first, ref T second) { T temp; temp = first; first = second; second = temp; } //To call the method, specify the type following method name SwapData <string> (ref firstValue, ref secondValue);
Dynamic C# was originally characterized as being a strongly typed language Compiler checks to ensure that only compatible values are attempting to be stored Variables can still be defined as objects and then cast as different data types during run time Additional boxing/unboxing is needed C# Programming: From Problem Analysis to Program Design
Dynamic Data Type An object defined using the dynamic keyword can store anything No unboxing or casting is necessary prior to their use With dynamic data types, the type checking occurs at run time Once defined as dynamic, the memory location can hold any value Dynamic types can be used for data types, method parameters or method return types
Dynamic Data Type (continued) dynamic intValue = 1000; dynamic stringValue = "C#"; dynamic decimalValue = 23.45m; dynamic aDate = System.DateTime.Today; Console.WriteLine("{0} {1} {2} {3}" , intValue, stringValue, decimalValue, aDate); C# 23.45 6/16/2013 12:00:00 AM Single dynamic memory location can hold values of different data types
var Data Type Variables declared inside a method can be declared using the var keyword Compiler determines the type One primary difference between dynamic and var is that var data items must be initialized when they are declared Commonly used by the LINQ technology
var Data Type (continued) Example var someValue = 1000; Implicitly typed by the compiler Compiler determines the type (integer in this case) Compiler infers the type of the variable from the expression on the right side of the initialization statement C# Programming: From Problem Analysis to Program Design
StudentGov Application Example Figure 11-18 Problem specification for StudentGov example C# Programming: From Problem Analysis to Program Design
StudentGov Application Example (continued) Table 11-1 Data fields organized by class C# Programming: From Problem Analysis to Program Design
StudentGov Example (continued) Figure 11-19 Prototype for StudentGov example C# Programming: From Problem Analysis to Program Design
StudentGov Example (continued) Figure 11-20 Class diagrams for StudentGov example C# Programming: From Problem Analysis to Program Design
StudentGov Example (continued) Figure 11-21 References added to StudentGov example C# Programming: From Problem Analysis to Program Design
StudentGov Example (continued) Figure 11-21 References added to StudentGov example (continued) C# Programming: From Problem Analysis to Program Design
StudentGov Example (continued) Table 11-2 PresentationGUI property values C# Programming: From Problem Analysis to Program Design
StudentGov Example (continued) Table 11-2 PresentationGUI property values (continued) C# Programming: From Problem Analysis to Program Design
StudentGov Example (continued) Table 11-2 PresentationGUI property values (continued) C# Programming: From Problem Analysis to Program Design
StudentGov Example (continued) Table 11-2 PresentationGUI property values (continued) C# Programming: From Problem Analysis to Program Design
StudentGov Example (continued) Figure 11-22 Setting the StartUp Project C# Programming: From Problem Analysis to Program Design
StudentGov Application Example (continued) Figure 11-23 Part of the PresentationGUI assembly C# Programming: From Problem Analysis to Program Design
StudentGov Application Example (continued) Figure 11-24 Output from StudentGov example C# Programming: From Problem Analysis to Program Design
Coding Standards Declare members of a class of the same security level together When declaring methods that have too many arguments to fit on the same line, the leading parenthesis and the first argument should be written on the same line Additional arguments are written on the following line and indented C# Programming: From Problem Analysis to Program Design
Resources Comparison of Unified Modeling Language Tools – http://en.wikipedia.org/wiki/List_of_UML_tools Generic Classes (C# Programming Guide) – http://msdn.microsoft.com/en-us/library/sz6zd40f(VS.80).aspx C# Station Tutorial: Interfaces – http://www.csharp-station.com/Tutorials/Lesson13.asp C# Programming: From Problem Analysis to Program Design
Chapter Summary Major features of object-oriented languages Abstraction Encapsulation Inheritance Polymorphism Multitier applications using component-based development methods
Chapter Summary (continued) Use inheritance to extend the functionality of user- defined classes Abstract classes Abstract methods Sealed classes Partial classes
Chapter Summary (continued) Interfaces Why polymorphic programming? Generics Generic classes Generic methods Dynamic data types var data types C# Programming: From Problem Analysis to Program Design
APPENDIX Making Stand-Alone Components Can take Person and Student classes (or any user-defined class) and store in library for future use. Compile class and create an assembly. Assemblies are units configured and deployed in .NET Classes can be compiled and stored as a dynamic link library (DLL) instead of into the EXE file type
APPENDIX Dynamic Link Library (DLL) Several options for creating components One option – compile source code into .dll file type Once you have a DLL, any application that wants to use it just adds a reference to the DLL That referenced file with the .dll extension becomes part of the application’s private assembly Can use the command line to create .DLL C# Programming: From Problem Analysis to Program Design
Using Visual Studio to Create DLL Files Figure 11-6 Creating a DLL component
Build Instead of Run to Create DLL Create the parent class first in order to use IntelliSense (for sub classes) To illustrate creating stand-along components, separate project created for Person and Student Because Visual Studio assigns the namespace name as the project name (Person), you should change the namespace identifier If you don’t change it, when you start adding a reference to a created DLL, it can become confusing Changed to PersonNamespace for the example C# Programming: From Problem Analysis to Program Design
Build Instead of Run to Create DLL After typing class, do not run it – select BUILD, Build Solution Figure 11-7 Attempting to run a class library file Create new project for subclasses (Student) Again, select Class Library template from Start page Change namespace identifier (StudentNamespace)
Build Instead of Run to Create DLL (continued) Add a new using statement to subclass In Student, add using PersonNamespace; To gain access to base class members in subclass, Add Reference in subclass to base class Use Solution Explorer window DLL is stored in Debug directory under the bin folder wherever you create the project C# Programming: From Problem Analysis to Program Design
Add Reference to Base Class One of the first things to do is Add a Reference to the Parent DLL Figure 11-8 Adding a reference to a DLL
Add Reference to Base Class (continued) Use Browse button to locate DLL Figure 11-9 Add Reference dialog box
Add Reference to Base Class (continued) Figure 11-10 Locating the Person.dll component
Adding a New Using Statement In the subclass class, if you simply type the following, you receive an error message public class Student : Person Figure 11-11 Namespace reference error
Adding a New Using Statement (continued) Notice fully qualified name To avoid error, could type: public class Student : PersonNamespace.Person Better option is to add a using directive using PersonNamespace; // Use whatever name you // typed for the namespace for Person After typing program statements, build the DLL from the Build option under the BUILD menu bar
Creating a Client Application to Use the DLL DLL components can be reused with many different applications Once the .DLL is in the library, any number of applications can reference it Instantiate objects of the referenced DLL Two steps Required Add a reference to the DLL components Include a using statement with the namespace name C# Programming: From Problem Analysis to Program Design
Creating a Client Application to Use the DLL (continued) Figure 11-12 DLLs referenced in the PresentationGUI class
Declaring an Object of the Component Type Declare object of the subclass (Student)…not the base class public class PresentationGUI : System.Windows.Forms.Form { private Student aStudent; Instantiate the object aStudent = new Student("123456789", "Maria", "Woo", "CS", "1111"); Use members of the derived, base, or referenced classes
Creating a Client Application to Use the DLL (continued) Figure 11-13 PresentationGUI output referencing two DLLs
Using ILDASM to View the Assembly (ILDASM): Intermediate Language Disassembler tool Assembly shows the signatures of all methods, data fields, and properties One option – display the source code as a comment in the assembly Can be run from the command line or from within the Visual Studio IDE
Using ILDASM to View the Assembly (continued) In order to use ILDASM in Visual Student, must be added as an external tool in Visual Studio (TOOLS, External Tools…) DLL files cannot be modified or viewed as source code Can use ILDASM to view DLL assemblies C# Programming: From Problem Analysis to Program Design
ILDASM to View the Assembly .ctors are constructors IL code for the method Data fields Properties converted to methods Figure 11-14 Student.dll assembly from ILDASM