Вы находитесь на странице: 1из 46

OOP with C#

What is OOP ?
Programming Methodology
Uses Objects to carryout Functionality

Discrete units of functionality


Objects Mimic real life entities Organized around objects instead of actions Organized around data rather than logic

OOP Benefits
Programs are organized around object that perform actions.
Programs no longer dependent on linear logic.

Easy, Safely Updated.


Programs relate to real life actions. Code Reuse

Definition of C# Class
Class is a custom User Defined Type (UDT) that is composed of

data and functions that act on data.


By Grouping data and functionality in a single UDT, we are able

to model software types after real-world enitities.

Scenario
We wish to build a class that maintains the name, current pay,

and employeeID for each worker. In addition, the Employee class defines one method named GiveBonus(), which increases an individuals current pay by some amount, and another named DisplayStats(), which prints out relavent statistics for this individual.

Class Diagram
Employee

Attributes: String Fname; Int empID; Float CurrPay;


Methods: Void GiveBonus(float amt); Void DispStats()

Attributes represent the internal state of a given instance of this class

Methods Provide a way to interact with an Objects state

Constructor
Constructor is used to initialize an object (instance) of a class. Constructor is a like a method without any return type.

Constructor has same name as class name.


Constructor follows the access scope (Can be private, protected,

public, Internal and external). Constructor can be overloaded.

Self-Reference in C#
this keyword is used whenever we wish to make reference to the current object .
The use of this keyword is to avoid clashes between the parameter names and names of your internal state variables

Default public Interface


The term refers to the set of public members that are directly accessible from an object variable.
Methods: Named units of work that model some behavior of a class
Properties: Accessor and mutator functions in disguise Public field data: Although public data is typically bad idea

Specifying Type Visibility: Public and Internal Types


Method Visibility used to constrain which members can be accessed from a given object Type Visibility used to establish which parts of the system can create the type themselves

Public types may be created by any other objects within the same assembly as well as by other external assemblies

Internal Classes Can only be created by types living within the same assembly and are not accessible from outside the assemblys bounds

Recapping the Pillars of OOP


Encapsulation: How well does this language hide an objects internal implementation?
Inheritance: How does this language promote code reuse? Polymorphism: How does this language let you treat related objects in a similar way?

Encapsulation
Hides the unnecessary implementation details from the

object user. DBReader d= new DBReader(); f.open(@c:\myfile); -------------------------f.close();

Inheritance: is-a and has-a


Allows to build new class definitions based on existing class

definitions. Allows to extend the behavior of a base class by inheriting core functionality into a subclass. A Hexagon is-a Shape that is-a Object

The is-a relationship

Inheritance: is-a and has-a


The containment/ delegation model, oralso known as has-a relation. a given class can define a member variable of another class and expose part or all of its functionality to the outside world

Car Radio

// Method of Car Void TurnOnRadio(bool on) { //Delegate to inner Radio radioObj.Power(on); }

Polymorphism
This trait captures languages ability to treat related objects the same way.
Classical Polymorphism Ad Hoc Polymorphism

Classical Polymorphism
Takes place in a language that also supports classical

Inheritance.
A base class can define a set of members that can be

overridden by a subclass.
Redefining how they respond to the same message

Ad Hoc Polymorphism
Allows objects that are not related by classical inheritance to

be treated in a similar manner, provided that every object has a method of the exact same signature.
They uses a technique called Late binding to discover at runtime

the underlying type of a given object

Encapsulation Services
The objects internal data should not be directly accessible from an

object instance.

We can alter the state of an object indirectly using accessor (get) and

mutator (set) methods.

Encapsulation provides a way to preserve the integrity of state data. Rather than defining public fields, we should get in the habit of

defining private data fields, which are indirectly manipulated using one of two main techniques: 1. Define a pair of traditional accessor and mutator methods. 2. Define a named property.

Enforcing Encapsulation using Traditional Accessors and Mutators


public class Employee { private string fullName; ... // Accessor. public string GetFullName() { return fullName; } // Mutator. public void SetFullName(string n) {

fullName = n;

}
}

Enforcing Encapsulation using Traditional Accessors and Mutators


// Accessor/mutator usage. public static int Main(string[] args) { Employee p = new Employee(); p.SetFullName(jai kriishna"); Console.WriteLine("Employee is named: {0}", p.GetFullName()); return 0; }

Another form of Encapsulation: Class Properties


Rather than requiring the user to call two discrete methods to get and set the sate data, the user is able to call what appears to be a single named field.
Type Properties always map to real accessor and mutator methods.

As a class designer we are able to perform any internal logic necessary before making the value assignment.

// Custom property for the EmpID data point. public class Employee { ... private int empID; // Property for the empID data point. public int EmpID { get { return empID;} set { empID = value; } } }

Static Properties
// Static properties must operate on static data! public class Employee { private static string companyName; public static string Company { get { return companyName; } set { companyName = value;} } ... }

// Set and get the name of the company that employs these people... public static int Main(string[] args) { Employee.Company = Btech, Inc"; Console.WriteLine("These folks work at {0} ", Employee.Company); ... }

Class Properties: ReadOnly WriteOnly


public class Employee { ... private string empSSN; public Employee(string FullName, int empID, float currPay, string ssn) { this.fullName = FullName; this.empID = empID; this.currPay = currPay; this.empSSN = ssn; } public string SSN { get { return empSSN; } } }

Pseudo-Encapsulation: Creating Read-Only Fields


Closely related to constant data is the notion of read-only field data

(which should not be confused with a read-only property).

Like a constant, a read-only field cannot be changed after the initial

assignment. However, unlike a constant, the value assigned to a read-only field can be determined at runtime, and therefore can legally be assigned within the scope of a constructor (but nowhere else).

This can be very helpful when you dont know the value of a field

until runtime (perhaps because you need to read an external file to obtain the value), but wish to ensure that the value will not change after that point.

Pseudo-Encapsulation: Creating Read-Only Fields


class MyMathClass { // Read-only fields can be assigned in ctors, // but nowhere else. public readonly double PI; public MyMathClass () { PI = 3.14;}
public void ChangePI() { PI = 3.14444; } }

The Second Pillar: Inheritance


Is-a relationship, MiniVan is-a Car Car class can be extended as a MiniVan Syntactically as: class MiniVan : Car

Regarding Multiple Base Classes


.NET platform demands that a given class have exactly one

direct base class. It is not possible to create a class type that directly derives from two or more base classes. // Illegal! The .NET platform does not allow // multiple inheritance for classes! class WontWork: BaseClassOne, BaseClassTwo {}

The sealed Keyword


sealed, prevents inheritance from occurring. When we mark a class as sealed, the compiler will not allow you

to derive from this type. // This class cannot be extended! sealed class MiniVan : Car {} // Error! Cannot extend a class marked with the sealed keyword! class DeluxeMiniVan: MiniVan {}

Controlling Base Class Creation with the base Keyword


static void Main(string[] args) { ... // Assume Manager has a constructor matching this signature: // (string fullName, int age, int empID, float currPay, string ssn, int numbOfOpts) Manager tom= new Manager(Tom", 50, 92, 100000, "33323-2322", 9000); Console.ReadLine(); }

Controlling Base Class Creation with the base Keyword


public Manager(string fullName, int age, int empID, float currPay, string ssn, int numbOfOpts) { // This field is defined by the Manager class. numberOfOptions = numbOfOpts; // Assign incoming parameters using the inherited properties of the parent class. ID = empID; Age = age; Name = fullName; Pay = currPay; // OOPS! This would be a compiler error, // as the SSN property is read-only! SocialSecurityNumber = ssn; }

Controlling Base Class Creation with the base Keyword


The 1st issue, we defined the SocialSecurityNumber property in the

parent is read-only; therefore we are unable to assign the incoming string parameter to this field, as seen in the final code statement of this custom constructor. The 2nd issue, we have indirectly created a rather inefficient constructor, given the fact that under C#, unless you say otherwise, the default constructor of a base class is called automatically before the logic of the derived constructor is executed. To implement our subclass constructors to explicitly call an appropriate custom base class constructor, rather than the default.

Controlling Base Class Creation with the base Keyword


public Manager(string fullName, int age, int empID, float currPay, string ssn, int numbOfOpts) : base(fullName, age, empID, currPay, ssn) { // This field is defined by the Manager class. numberOfOptions = numbOfOpts; } The base keyword in the constructor signature, which always indicates a derived constructor is passing data to the immediate parent constructor. In this situation, we are explicitly calling the five-argument constructor defined by Employee and saving unnecessary calls during the creation of the child class

Keeping Family Secrets: The protected Keyword


public items are directly accessible from anywhere, while private

items cannot be accessed from any object beyond the class that has defined it. When a base class defines protected data or protected members, it establishes a set of items that can be accessed directly by any descendent. If we wish to allow the SalesPerson and Manager child classes to directly access the data sector defined by Employee, we can update the original Employee class definition as follows:

// protected state data. partial class Employee { // Derived classes can now directly access this information. protected string empName; protected int empID; protected float currPay; protected int empAge; protected string empSSN; protected static string companyName; ... }

Adding a Sealed Class


sealed class PTSalesPerson : SalesPerson { public PTSalesPerson(string fullName, int age, int empID, float currPay, string ssn, int numbOfSales) :base (fullName, age, empID, currPay, ssn, numbOfSales) { } // Assume other members here... }

Programming for Containment/Delegation


lets examine the has-a relationship (also known as the containment/delegation model or aggregation) // This type will function as a contained class. class BenefitPackage { public double ComputePayDeduction() { return 125.0; } } to expose the functionality of the contained object to the outside world requires delegation. Delegation is simply the act of adding members to the containing class that make use of the contained objects functionality

public partial class Employee { // Contain a BenefitPackage object. protected BenefitPackage empBenefits = new BenefitPackage(); // Expose certain benefit behaviors of object. public double GetBenefitCost() { return empBenefits.ComputePayDeduction(); } // Expose object through a custom property. public BenefitPackage Benefits { get { return empBenefits; } set { empBenefits = value; } } ... }

Understanding Nested Type Definitions


Nested types allows to gain complete control over the access level

of the inner type, as they may be declared privately


Because a nested type is a member of the containing class, it can

access private members of the containing class.


Nested type is only useful as a helper for the outer class, and is

not intended for use by the outside world.

// Employee nests BenefitPackage. public partial class Employee { // BenefitPackage nests BenefitPackageLevel. public class BenefitPackage { public enum BenefitPackageLevel { Standard, Gold, Platinum } public double ComputePayDeduction() { return 125.0; } } ... }

The Third Pillar: C#s Polymorphic Support


public partial class Employee { public void GiveBonus(float amount) { currPay += amount; } ... } ________________________________________ class Manager : Employee { ... public override void GiveBonus(float amount) { base.GiveBonus(amount); Random r = new Random(); numberOfOptions += r.Next(500); } }

Understanding Abstract Classes


abstract partial class Employee { ... } // What exactly does this mean? Employee X = new Employee();

Understanding Base Class/Derived ClassCasting Rules


Under the .NET platform, the ultimate base class in the system is System.Object. Therefore, everything is-a Object and can be treated as such: // A Manager "is-a" System.Object. object frank = new Manager("Frank Zappa", 9, 3000, 40000, "111-111111", 5);

// A Manager "is-an" Employee too. Employee moonUnit = new Manager("MoonUnit Zappa", 2, 3001, 20000, "101-11-1321", 1); // A PTSalesPerson "is-a" SalesPerson. SalesPerson jill = new PTSalesPerson("Jill", 834, 3002, 100000, "111-121119", 90);

Understanding Base Class/Derived ClassCasting Rules


The first law of casting between class types is that when two

classes are related by an is-a relationship, it is always safe to store a derived type within a base class reference. Formally, this is called an implicit cast. second law of casting: we must explicitly downcast using the C# casting operator.

Вам также может понравиться