c# summer course - lecture 4
DESCRIPTION
C# summer training for FCIS, 2010. Lecture 4TRANSCRIPT
Introduction to C#
Lecture 4
FCISSummer training 2010, 1st year.
Contents
Inheritance Calling base class constructors The protected keyword Dynamic binding; virtual and override Polymorphism and assignment compatibility All classes inherit from object The need for down casts Abstract classes Examples
Inheritance
class Employee
{
int salary;
public Employee( ) { salary = 100; }
public void Raise( ) { salary += 50;}
}
class Teacher : Employee
{
string researchTopic;
}
In this code, the class Teacher extends the employee class. This means:
– Members of Employee like salary, Raise( ) are also members of teacher (Inheritance).
– Objects of type teacher can be assigned to variables of type employee (Polymorphism).
Inheritance
class Test
{
static void Main()
{
Teacher t = new Teacher();
t.Raise( ); // OK
Employee e1 = new Employee(); // OK
Employee e2 = new Teacher(); // OK
}
}
Calling base constructors
It is important for the derived class's constructor to call the constructor of it's parent.
Calling the base constructor is done via the base keyword.
Some useful rules: If (a) The derived constructor (e.g Teacher)
doesn't call a base constructor, and (b) The base has a parameterless constructor, then the base parameterless constructor is called automatically.
Otherwise, the derived constructor must call the base constructor explicitly and give it parameters.
Calling base constructors - 2This code is correct, since Teacher's default constructor calls
Employee's default constructor
class Employee {
int salary;
public Employee( ) { salary = 100; }
public void Raise( ) { salary += 50;}
}
class Teacher : Employee {
string researchTopic;
}
Calling base constructors - 3This code is also correct, since Teacher's Employee's default
constructor is still called. class Employee {
int salary;
public Employee( ) { salary = 100; }
public void Raise( ) { salary += 50;}
}
class Teacher : Employee {
string researchTopic;
public Teacher() { }
}
Calling base constructors - 4But this code is incorrect, since the compiler cannot know what
parameters to give to Employee's only constructor! class Employee {
int salary;
public Employee(int s) { salary = s; }
public void Raise( ) { salary += 50;}
}
class Teacher : Employee {
string researchTopic;
public Teacher() { } // ???
}
Calling base constructors - 4Now the code is correct, since all of Teacher's constructors give
the required parameters to the base class's constructors. class Employee {
int salary;
public Employee(int s) { salary = s; }
public void Raise( ) { salary += 50;}
}
class Teacher : Employee {
string researchTopic;
public Teacher() : base(100) { } // OK
public Teacher(int _salary): base(_salary) {} // OK
}
Protected - 1
class Employee
{
int salary;
public Employee( ) { salary = 100; }
public void Raise( ) { salary += 50;}
}
class Teacher : Employee
{
string researchTopic;
public Teacher( )
{
salary = 500; // WRONG! 'salary' is private
}
}
Protected - 2
class Employee
{
protected int salary;
public Employee( ) { salary = 100; }
public void Raise( ) { salary += 50;}
}
class Teacher : Employee
{
string researchTopic;
public Teacher( )
{
salary = 500; // OK! 'salary' is protected
}
}
Overriding
A class like Teacher inherits all data members and methods from it's parent class.
But what if some of Teacher's behavior is different from employee?
For example, what if Raise( ) should increment the salary by a different amount (say 51 instead of 50?).
In this case the derived class can override the method from its parent class.
But the parent class must allow overriding of this method by making it virtual.
Overriding class Employee {
int salary;
public Employee() { salary = 100; }
public virtual void Raise( ) { salary += 50;}
}
class Teacher : Employee {
string researchTopic;
public Teacher() { }
public override void Raise( ) { salary += 51; }
}
Dynamic binding class Employee {
int salary;
public Employee() { salary = 100; }
public virtual void Raise( ) { salary += 50;}
}
class Teacher : Employee {
string researchTopic;
public Teacher() { }
public override void Raise( ) { salary += 51; }
}
class Test {
static void Main( ) {
Employee e = new Teacher( );
e.Raise( );
} } Is e.salary now equal to 150 or 151?
Object...
All classes inherit from object. So an instance of any class can be assigned to a variable of type object, stored in an array of objects, passed to functions that take objects....etc
Also, object includes functions like ToString( ), which (a) Can be overriden and (b) Are used by standard .net code like Console.WriteLine and list boxes.
What about value types (which are not classes)? When you assign them to objects they are first copied into an object with a reference. This is called boxing.
Downcasts
Employee e1, e2;
Teacher t1, t2, t3;
e1 = new Employee( ); // OK, same type
Teacher t1 = new Teacher( );
e1 = t1; // OK, 'Teacher' is a
// subtype of 'Employee'
Teacher t2 = e2; // WRONG!
Teacher t3 = (Teacher) e2; // OK for the compiler
The last line is a downcast. It means "assume e2 is really a reference to a 'Teacher' object"
There will be a runtime check that this is the case, and an exception will be thrown if e2 isn't the correct type. Otherwise the program will go on normally.
Downcasts are sometimes needed, but are usually a sign of bad design; use polymorphism instead.
Abstract classesclass Shape {
public virtual double GetArea() { ... }
}
class Square : Shape {
double side;
public Square(double s) { side = s;}
public override double GetArea() { return side*side;}
}
class Circle : Shape {
double radius;
public Circle(double r) { radius = r;}
public override double GetArea()
{ return Math.PI * radius*radius;}
}
نضع ماذاهنا؟؟؟
Abstract classesabstract class Shape {
public abstract double GetArea();
}
class Square : Shape {
double side;
public Square(double s) { side = s;}
public override double GetArea() { return side*side;}
}
class Circle : Shape {
double radius;
public Circle(double r) { radius = r;}
public override double GetArea()
{ return Math.PI * radius*radius;}
}
Abstract classes Abstract classes represent common concepts
between many concrete classes. A class that has one or more abstract functions must
also be declared abstract. You cannot create instances of abstract classes (but
you're free to create references whose types are abstract classes).
If a class inherits from an abstract class, it can become concrete by overriding all the abstract methods with real methods. Now it can be instantiated.
Extra: A simple dialog box...
To end the session, we'll show how to create a simple dialog box that reads a name from the user...
Creating the dialog box...
btnOk btnCancel
txtName
Value Property Object
btnOk AcceptButton Form
btnCancel CancelButton Form
OK DialogResult btnOk
Cancel DialogResult btnCancel
Creating the dialog box...
In Form2:
public string GetName( )
{
return txtName.Text;
}
Using a dialog box...
In Form1 void btnGetName_Click(object sender, EventArgs e)
{
Form2 f = new Form2();
DialogResult r = f.ShowDialog( ); // Show modal
if(r == DialogResult.OK)
{
string name = f.GetName( );
lblResult.Text = f;
}
}