Chapter 4 Object Oriented Programming with C#
Nov 07, 2014
Chapter 4
Object Oriented Programming with C#
• A Class is a customer user-defined type that is composed of data and functions that act on this data.
Employee
attributes:
string fullName
int empID
float currPay
Methods
Employee()
Employee(string fullName, int empID, float currPay)
void GiveBonus(float amout)
Void DisplayStats();
Method Overloading• When a class has a set of identically named members that differ by the
number or type of parameters, the member in question is said to be overloaded.Eg:
class Triangle{
public void Draw( int x, int y, int height, int width);public void Draw( float x, float y, float height, float
width);public void Draw(Point upperLeft, Point bottomRight);public Draw (Rect r);
}• When a class member is overloaded, the return type alone is not unique
enough.public float GetX();public int GetX();
Self Reference
• “this” keyword• This keyword is used whenever the reference is to be made to the
current object.• Static member functions of a type cannot use “this” keyword.
public Employee(string FullName, int empID, float currPay){
this.fullName = FullName;this.empID = empID;this.currPay = currPay;this.empSSN = ssn;
}
public Employee(string fullName) : this(fullName, 3333, 0.0F) { }
Default public Interface
• Set of public members that are directly accessible from an object variable. – Method visibility – units that model the behavior of the
class.– Properties visibility – Accessor and mutator functions– Field Data visibility - Data
– Type visibility – which parts of the system can create type themselves. If not specified, it is assumed to be internal.
public class HelloClass
{…
}– This would mean that all .Net assemblies can use this
class.– Any .NET type can be defined to have public or
internal visibility.
using System;namespace Hellotypes{
internal struct x{
private int myX;public int GetMyX() { return myX;}public x(int x) {myX = x;}
}internal enum Letters{a=0, b=1, c=2}
public class HelloClass{
public static int Main(string[] args){
X theX = new X(26);Console.WriteLine(“{0}\n{1}”, theX.GetMyX(), Letters.b.toString());return 0;
}}
Pillars of OOP
• Encapsulation: how well does this language hide the object’s internal implementation?
• Inheritance: How does the language promote code reuse?– (Classical) Is-a – Eg: Hexagon-shape-object
– has-a relationship –Eg: car-radio
• Polymorphism: How does this language let you treat related objects in a similar way?– Classical – Base class defines a set of members that can be overridden
by subclass. Eg; Draw
– Ad-hoc – Late binding
Encapsulation
• Black box programming• An object’s internal data should not be directly
accessible from an object instance.– public– private– protected– protected internal
• Define the data fields as private– Define a pair of accessor and mutator methods– Define a named property
using system;public class Department{
private string departname;// Accessor.public string GetDepartname(){
return departname;}// Mutator.public void SetDepartname( string a){
departname=a;}public static int Main(string[] args){
Department d = new Department(); d.SetDepartname("ELECTRONICS"); Console.WriteLine("The Department is :"+d.GetDepartname()); return 0;
}}
public string Name
{
get { return fullName; }
set { fullName = value;}
}
// Property for the empID.
public int EmpID
{
get {return empID;}
set
{
empID = value;
}
}
// Property for the currPay.
public float Pay
{
get {return currPay;}
set {currPay = value;}
}
class TimePeriod{ private double seconds;
public double Hours { get { return seconds / 3600; } set { seconds = value * 3600; } }}class Program{ static void Main() { TimePeriod t = new TimePeriod();
// Assigning the Hours property causes the 'set' accessor to be called. t.Hours = 24;
// Evaluating the Hours property causes the 'get' accessor to be called. System.Console.WriteLine("Time in hours: " + t.Hours); }}
• Write a C# class Student with the following attributes– usn (string)– attendance (int)– internalMarks (float)
• Create mutators and accessors to access usn and attendance.
• Create a property to access internalMarks. • The attendance and internalMarks returned should be in
percentage. (assume total no of classes = 60 and Max internal = 25)
• Write a main function that to demonstrate the usage.
C# Inheritance Support
using System;
public class Employee
{
// protected data for kids.
protected string fullName;
protected int empID;
private float currPay;
}
namespace Employees{
public class Manager : Employee{
private ulong numberOfOptions;public ulong NumbOpts {
get {return numberOfOptions;}set { numberOfOptions = value;}
}}public class SalesPerson : Employee{
protected int numberOfSales;public int NumbSales {
get {return numberOfSales;}set { numberOfSales = value;}
}}
}
public static int Main(string[] args)
{
SalesPerson stan = new SalesPerson();
stan.EmpID = 100;
stan.setFullName("Stan the Man");
stan.NumbSales = 42;
stan.currPay; //Error
return 0;
}
public class Radio
{
public void TurnOn(bool on)
{
if(on)
Console.WriteLine("Jamming...");
else
Console.WriteLine("Quiet time...");
}
}
public class Car {
private int currSpeed;private int maxSpeed;private string petName;bool carIsDead;public Car() {
maxSpeed = 100;carIsDead = false;
}public Car(string name, int max, int curr) {
currSpeed = curr;maxSpeed = max;petName = name;carIsDead = false;
}// A car has-a radio.private Radio theMusicBox = new Radio();
public void CrankTunes(bool state){
// Tell the radio play (or not).// Delegate request to inner object.theMusicBox.TurnOn(state);
}public void SpeedUp(int delta){
// If the car is dead, just say so...if(carIsDead){
Console.WriteLine("{0} is out of order....", petName );}else // Not dead, speed up. {
currSpeed += delta;if(currSpeed >= maxSpeed) {
Console.WriteLine("Sorry, {0} has overheated...", petName );carIsDead = true;
}else
Console.WriteLine("=> CurrSpeed = {0}", currSpeed); } }
public class CarApp{
public static int Main(string[] args){
// Make a car.Car c1;c1 = new Car("SlugBug", 100, 10);
// Jam some tunes.Console.WriteLine("***** Turing on radio for SlugBug *****");c1.CrankTunes(true);
// Speed up.Console.WriteLine("\n***** Speeding up *****");for(int i = 0; i < 10; i++)
c1.SpeedUp(20);
// Shut down.Console.WriteLine("\n***** Turing off radio for SlugBug *****");c1.CrankTunes(false);return 0;
} }
• Create a namespace college
• Base class: Person – Attributes: name, address, Phone
• Derived class: Student– Attributes: usn, branch, subjectsTaken
• Derived class: Teacher– Attributes: subjectTaught,
• Helper class: Subject– Attributes: SubjectName, MaxAtt, MaxIM
• Create a Main function to – create an instance of a student, initialize it to your details. – create an instance of a teacher, initialize it to a teacher’s details.– Display all the details.
using System;namespace College{ public class Person { protected string name; protected string address; protected string phone; public Person(string newName, string newAddress, string newPhone) { this.name = newName; this.address = newAddress; this.phone = newPhone; } public string getName() { return name; } public string getAddress() { return address; } public string getPhone() { return phone; } }
class Subject { private string subjectName; private int MaxAtt; private int MaxIM; public Subject(string newSubjectName, int newMaxAtt, int newMaxIM) { this.subjectName = newSubjectName; this.MaxAtt = newMaxAtt; this.MaxIM = newMaxIM; } public string getsubjectName() { return subjectName; } public int getMaxAtt() { return MaxAtt; } public int getMaxIM() { return MaxIM; } }
class Student : Person { private string usn; private string branch; private Subject subjectsTaken;
public Student(string newName, string newAddress, string newPhone, string newUsn, string newBranch, Subject mySubject): base(newName, newAddress, newPhone)
{ this.usn = newUsn; this.branch = newBranch; this.subjectsTaken = mySubject;
}
public string getUsn() { return usn; } public string getBranch() { return branch; } public Subject getSubjectTaken() { return subjectsTaken; } }
class Teacher : Person { private Subject SubjectTaught; public Teacher(string newName, string newAddress, string newPhone, Subject
mySubject) : base(newName, newAddress, newPhone) { this.SubjectTaught = mySubject; } public Subject getSubjectTaught() { return SubjectTaught; } }
class StudentApp { public static void Main() { Subject cSharp = new Subject("C#", 64, 25); Student stud1 = new Student("Sujatha", "Anandnagar", "9885655627", "1AT02CS007", "CSE",
cSharp); Teacher t1 = new Teacher("Seema", "Hebbal", "080-765676", cSharp);
Console.WriteLine("Student Name:" + stud1.getName()); Console.WriteLine("Student Address:"+stud1.getAddress()); Console.WriteLine("Student Phone:" + stud1.getPhone()); Console.WriteLine("Student USN:" + stud1.getUsn()); Console.WriteLine("Student branch:" + stud1.getBranch()); Console.WriteLine("Student Subject Taken:" + stud1.getSubjectTaken().getsubjectName());
Console.WriteLine("Teacher Name:" + t1.getName()); Console.WriteLine("Teacher Address:" + t1.getAddress()); Console.WriteLine("Teacher Phone:" + t1.getPhone()); Console.WriteLine("Teacher Subject Taught:" + t1.getSubjectTaught().getsubjectName()); Console.Read(); } }}
Output
Student Name:Sujatha
Student Address:Anandnagar
Student Phone:9885655627
Student USN:1AT02CS007
Student branch:CSE
Student Subject Taken:C#
Teacher Name:Seema
Teacher Address:Hebbal
Teacher Phone:080-765676
Teacher Subject Taught:C#
A C# property actually maps to a get_/set_ pair. (The reverse is not true)Eg:
public class Employee{
private string empSSN;public string SSN
{get { return empSSN;}set{ empSSN = value;}
}
//ERRORpublic string get_SSN()
{ return empSSN;}
public string set_SSN(string val){empsSN = val;}
}
Read-Only and Write-Only properties
• To configure a read-only property, simply build a property without a corresponding set block.
• If you wish to have write-only property, omit the get block.
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;}}
}
Static properties
public class Employee{
private static string companyName;
public static string Company{
get { return companyName;}set { companyName = value;}
}
//Usage: Employee.Company = “Infosys Inc”;Console.WriteLine(“The folks work at {0}”, Employee.Company);
Static Constructor
• Static constructors can be used to assign values to static data• This assignment always happens by default.
public class Employee{
private static string companyName;static Employee(){
companyName = “Infosys Inc”;}
}//UsageConsole.WriteLine (“These folks work at {0}”, Employee.Company);
Read-Only fields (Psudo encapsulation)
public class Employee{
public readonly string SSNField;public Employee(string FullName, int empID, float currPay, string ssn){
this.fullName = FullName;this.empID = empID;this.currPay = currPay;this.empSSN = ssn;this.SSNField = ssn;
}}
//ErrorEmployee brenner = new Employee();brenner.SSNField = “666-66-666”;
Preventing Inheritance
public sealed class PTSalesPerson : SalesPerson
{
Public PTSalesPerson(string fullName, int empID, float currPay, string ssn, int numberOfSales)
{
//Logic
}
}
//Error
Public class ReallyPTSalesPerson: PTSalesPerson
Containment and Delegation (has-a) relationship
• Eg: Car, radio
Nested Type Definitions public class Car{
private class Radio{
public void TurnOn(bool on){
if (on) Console.WriteLine(“Jamming…”);
elseConsole.WriteLine(“Quiet Time…”);
}}private Radio theMusicBox = new Radio();
}
• Nested type could be public or private (Not true for other types)• Car$Radio
C# Polymorphic supportpublic class Employee
{
protected string fullName;
protected int empID;
protected float currPay;
protected 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 void GiveBonus(float amount)
{
currPay + = amount;
}
}
public class SalesPerson : Employee{
protected int numberOfSales;
public SalesPerson(string FullName, int empID, float currPay, string ssn, int numbOfSales)
: base(FullName, empID, currPay, ssn){
numberOfSales = numbOfSales;}
}
public class Manager : Employee{
private ulong numberOfOptions;
public Manager(string FullName, int empID,
float currPay, string ssn, ulong numbOfOpts)
: base(FullName, empID, currPay, ssn)
{
// This point of data belongs with us!
numberOfOptions = numbOfOpts;
}
}
Manager Chucky = new Manager(“Chucky”, 92, 10000, “333-33-3333”, 9000);
Chucky.GiveBonus();
SalesPerson fran= new Manager(“Fran”, 93, 3000, “999-99-9999”, 31);
Chucky.GiveBonus();
public class Employee
{
protected string fullName;
protected int empID;
protected float currPay;
protected 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 virtual void GiveBonus(float amount)
{
currPay + = amount;
}
}
public class SalesPerson : Employee{
protected int numberOfSales;
public SalesPerson(string FullName, int empID, float currPay, string ssn, int numbOfSales)
: base(FullName, empID, currPay, ssn){
numberOfSales = numbOfSales;}public override void GiveBonus(float amount){
int salesBonus = 0;
if(numberOfSales >= 0 && numberOfSales <= 100) salesBonus = 10;
else if(numberOfSales >= 101 && numberOfSales <= 200)salesBonus = 15;
elsesalesBonus = 20; // Anything greater than
200.
base.GiveBonus(amount * salesBonus);}
}
public class Manager : Employee
{
private ulong numberOfOptions;
public Manager(string FullName, int empID,
float currPay, string ssn, ulong numbOfOpts)
: base(FullName, empID, currPay, ssn)
{
// This point of data belongs with us!
numberOfOptions = numbOfOpts;
}
public override void GiveBonus(float amount)
{
// Increase salary.
base.GiveBonus(amount);
// And give some new stock options...
Random r = new Random();
numberOfOptions += (ulong)r.Next(500);
}
}
Manager Chucky = new Manager(“Chucky”, 92, 10000, “333-33-3333”, 9000);
Chucky.GiveBonus(300);
SalesPerson fran= new Manager(“Fran”, 93, 3000, “999-99-9999”, 31);
Chucky.GiveBonus(200);
abstract Classes and abstract methods• You can directly create instances of Employee• This is rather odd.• Better design would be to prevent the ability to directly
create a new Employee instance. • Once a class is abstract, it may contain any number of
abstract methods• Abstract methods can be used when a method is to be
defined that does not supply a default implementation.
abstract public class Employee{
//Logic}
Object
Shape
Hexagon
Circle
Void Draw()
Draw()
Draw()
namespace Shapes{
public abstract class Shape{
protected string petName;
// Constructors.public Shape(){petName = "NoName";}public Shape(string s){
this.petName = s;}
public virtual void Draw(){
Console.WriteLine(“Shape.Draw”);}
public string PetName{
get {return this.petName;}set {this.petName = value;}
}}
public class Circle : Shape
{
public Circle(){}
// Call base class constructor.
public Circle(string name): base(name){}
// Circle does not override draw
}
public class Hexagon : Shape{
public Hexagon(){}public Hexagon(string name): base(name){}
public override void Draw(){Console.WriteLine("Drawing " + PetName + " the
Hexagon");}
}
public class ShapesApp{ public static int Main(string[] args) {
// The C# base class pointer trick.Shape[] s = {new Hexagon(), new Circle(), new Hexagon("Mick"),
new Circle("Beth"), new Hexagon("Linda")};
for(int i = 0; i < s.Length; i++){
s[i].Draw();}
}}
namespace Shapes{
public abstract class Shape{
protected string petName;
// Constructors.public Shape(){petName = "NoName";}public Shape(string s){
this.petName = s;}
public abstract void Draw();
public string PetName{
get {return this.petName;}set {this.petName = value;}
}}
public class Circle : Shape
{
public Circle(){}
// Call base class constructor.
public Circle(string name): base(name){}
public override void Draw()
{
Console.WriteLine("Drawing " + PetName + " the Circle");
}
}
public class Hexagon : Shape{
public Hexagon(){}public Hexagon(string name): base(name){}
public override void Draw(){Console.WriteLine("Drawing " + PetName + " the
Hexagon");}
}
public class ShapesApp{ public static int Main(string[] args) {
// The C# base class pointer trick.Shape[] s = {new Hexagon(), new Circle(), new Hexagon("Mick"),
new Circle("Beth"), new Hexagon("Linda")};
for(int i = 0; i < s.Length; i++){
s[i].Draw();}
}}
Versioning• C# allows derived classes to contain methods with the same name as base
class methods.
• The base class method must be defined virtual.
• If the method in the derived class is not preceded by new or override keywords, the compiler will issue a warning and the method will behave as if the new keyword were present.
• If the method in the derived class is preceded with the new keyword, the method is defined as being independent of the method in the base class.
• If the method in the derived class is preceded with the override keyword, objects of the derived class will call that method rather than the base class method.
• The base class method can be called from within the derived class using the base keyword.
• The override, virtual, and new keywords can also be applied to properties, indexers, and events.
public class MyBase { public virtual string Meth1() { return "MyBase-Meth1"; } public virtual string Meth2() { return "MyBase-Meth2"; } public virtual string Meth3() { return "MyBase-Meth3"; }}
Versioning
class MyDerived : MyBase { // Overrides the virtual method Meth1 using the override keyword: public override string Meth1() { return "MyDerived-Meth1"; }
// Explicitly hide the virtual method Meth2 using the new keyword public new string Meth2() { return "MyDerived-Meth2"; }
// Because no keyword is specified in the following declaration // a warning will be issued to alert the programmer that // the method hides the inherited member MyBase.Meth3(): public string Meth3() { return "MyDerived-Meth3"; }
public static void Main() { MyDerived mD = new MyDerived(); MyBase mB = (MyBase) mD;
System.Console.WriteLine(mB.Meth1()); System.Console.WriteLine(mB.Meth2()); System.Console.WriteLine(mB.Meth3());}
Output
MyDerived-Meth1 MyBase-Meth2 MyBase-Meth3
Casting between Types
• Implicit cast operations
• //Manager “is-a” object• Object frank = new Manager(“Frank”, 9, 40000, “111-11-1111”, 5);
• //Manager “is-a” Employee• Employee moonunit= new Manager(“MoonUnit”, 9, 40000, “111-15-1111”,
5);
• //PTSalesPerson is a SalesPerson• SalesPerson jill = new PTSalesPerson(“Jill”, 834, 4000, “145-11-1111”, 5);
• First law of Casting: • When two classes are related by a “is-a” relationship, it is always safe
to reference a derived class using a base class reference.
public class TheMachine(){
Public static void FireThisPerson(Employee e){
//Remove from database//Get key and pencil sharpener from fired Employee
}}
Employee moonunit= new Manager(“MoonUnit”, 9, 40000, “111-15-1111”, 5);TheMachine.FireThisPerson(moonunit);
SalesPerson jill = new PTSalesPerson(“Jill”, 834, 4000, “145-11-1111”, 5);TheMachine.FireThisPerson(jill)
Object frank = new Manager(“Frank”, 9, 40000, “111-11-1111”, 5);TheMachine.FireThisPerson(frank); //Error
You cannot treat a base type reference as a derived type without first performing an explicit cast !
TheMachine.FireThisPerson((Employee)frank);
Determining the Type of Employee
public class TheMachine{
public static void FireThisPerson(Employee e){
if (e is SalesPerson){Console.WriteLine(“Lost a salesperson names {0}”, e.getfullName());Console.WriteLine(“{0} made {1} sales…”, e.GetFullName,
((SalesPerson)e).NumbSales);}
if (e is Manager){Console.WriteLine(“Lost a Manager names {0}”, e.getfullName());Console.WriteLine(“{0} had {1} stock options…”, e.GetFullName,
((Manager)e).NumbOpts);}
}}
public class TheMachine{
public static void FireThisPerson(Employee e){
SalesPerson p = e as SalesPerson;if (p != null){Console.WriteLine(“Lost a salesperson names {0}”, p.getfullName());Console.WriteLine(“{0} made {1} sales…”, p.getFullName(),
p.NumbSales);}else{
Manager m = e as Manager;if (m != null){
Console.WriteLine(“Lost a Manager names {0}”, m.getfullName());
Console.WriteLine(“{0} had {1} stock options…”, m.getFullName(), m.NumbOpts);
} } } }
Numerical casts
• int x = 30000;• byte b = (byte) x; //Loss of information, so cast explicitly
• byte b = 30;• int x = b; //No loss
1. The present population of two countries, namely My Country and Your Country are 817 million and 1.088 billion respectively. Their rates of population growth are 2.1% and 1.3% respectively. Write a C# program that determines the number of years until the population of My Country exceeds that of your country.
2. Enter two non-zero numbers. Write a program in C# to display the highest common factor and lowest common multiple.
3. Write a program to display the Fibonacci series up to N in C#.
4. Design a C# program to define a structure:
Student<USN, Name, Marks, Branch> Here, Branch is of type enum, with members <CSE, ISE, ELNS, EE, IT>.
Add Appropriate constructor and also a method to hike the marks by 10% to only CSE students. Show creation of some student objects and the way to call these methods.
1. When a class has a set of identically named members that differ by the return types, the method is said to be overloaded (True/False)
2. ________ keyword is used for self-reference in C#
3. All static members of a class can refer to themselves using the this keyword.
4. Point out the error in this code, if any.class Employee
{
int empID;
public Employee(int empID) { this.empID = empID;}
public Employee():this(007){}
}
5. What is a the default Public Interface of a Type?
6. A Type can have the visibility ___________ or _________
7. _____________ pillar of OOP lets you extend the behavior of a class.
8. What is Classical inheritance?
9. What is Classical Polymorphism?
10. Give one keyword in C# that enforces Encapsulation.
11. What are accessor and mutator functions?
12. Write a Property to provide readonly access this Datafield.
private int empID;
13. The Properties map to _____ and __________ methods.
14. A static constructor can be used to ___________________
15. How can read-only Fields be declared?
16. Multiple inheritance is supported by C# (True/False)
17. _________ keyword can be used to Prevent Inheritance.
18. __________ relationship is also known as Containment/Delegation model.
19. Nested Types can have visibility _________
20. A base class can enforce Polymorphism using the ________ keyword.
21. What are abstract classes?
22. ________ keyword is prefixed to a method is it needs to break its relationship with the base class.
23. _________ operators are used to determine the “type of” an object.
24. Numerical casts from smaller numerical type to higher numerical type should be explicit. (true/False)