820 likes | 956 Views
Windows Programming Using C#. Classes & Interfaces. Contents. Classes Inheritance Operator Overloading Structs Interfaces. C# Classes. The class is the main data structure in C# It blends ideas from both C++ and Java All methods are declared inline, as in Java No C++ style header files
E N D
Windows Programming Using C# Classes & Interfaces
Contents • Classes • Inheritance • Operator Overloading • Structs • Interfaces
C# Classes • The class is the main data structure in C# • It blends ideas from both C++ and Java • All methods are declared inline, as in Java • No C++ style header files • Supports only single inheritance • Inheritance syntax from C++ • Allows multiple classes to be declared in one file like C++ • Methods can be used before being declared
Class Declaration [attributes][access-modifiers]class ident [:base-class] {class-body} • Attributes & modifiers discussed later • For now, just use public • An optional base class can be used for inheritance
Class Declaration using System; public class Person { string name; int age; public Person(string nm, int ag) { name = name; age = ag; } public string getName() { return name; } }
Object Creation • Primitive types like int, char, etc. are value types and are created on the stack • Objects are reference types and are created on the heap • Declare an object reference variable • Use the new operator to create a class instance on the heap • Assign this new instance to the reference variable
Object Creation • Person p = new Person(“Ann”, 34); • This creates a new instance on the heap • The constructor for the new instance is invoked • The reference to the new instance is assigned to the variable • The object will be destroyed when there are no more references to it and it is reclaimed by the garbage collector
Constructors • A constructor is a special method with the same name as the class • It is run to initialize the class • Before it is run the class is undifferrentiated memory • After it is run, the memory is an instance of the class
Constructors • Constructors never have a return type • Constructors are usually public • Constructors may be overloaded • If no constructor is provided, the CLR will create one which does nothing • If any constructor is provided, no default constructor will be created
Member Variable Initialization • C# allows you to initialize a member variable when it is declared • int day = 30; • This is called an initializer • If you do not provide an initializer, a default value is assigned • This means that there are no uninitialized variables in C#
Copy Constructors • A copy constructor is simply a constructor which • accepts an instance of the same class as a parameter and • makes a copy of it • You must create a copy constructor if you need one, the compiler will not create one for you public Person(Person p) { name = p.name; age = p.age; }
This • this is a keyword referencing the current object • It can be used in any non-static class • It can be used to • Disambiguate parameters public Person(string name) { this.name = name; } • Pass a reference to the current object List.add(this);
Static Members • Classes have two types of members • Instance members • Every class instance has its own copy • Static members • The member is associated with the class, not the instance • All instances access the same members stored with the class • Must be qualified with the class name, NOT the name of an instance
Static Methods • Static methods are not associated with an instance and have no this reference • Static methods cannot refer to non-static members • Static methods are useful for • Utility operations associated with the class • Operations which modify the static data of a class
Static Constructors • Are invoked to initialize static members • Are invoked before any other constructors • A static constructor cannot have an access modifier (ie. public) • A static constructor cannot access any non-static members
Destructors • C# has a garbage collector • When there are no more references to an object, it is marked for destruction • Some time later, the garbage collector will actually destroy the object • Unlike in Java, the object is guaranteed to be destroyed
Destructors • A C# destructor looks like a C++ destructor • ~MyClass() { /* do destructor work here */ } • That is the end of the similarities • You only need a destructor if you have to free unmanaged resources like file handles • References to managed objects will be handled by the garbage collector without the need for a destructor • Never call a destructor directly, the garbage collector will call it for you
Finalize • This syntax is really a shortcut for calling a Finalize() method which will chain up to the base class • It is translated to ~MyClass() { try { // work of destructor } finally { base.Finalize(); } }
Dispose • The problem with destructors is that they will not run until the object is reclaimed by the garbage collector • This means that precious resources might be held for longer than necessary • You can fix this by • Implementing the IDisposable interface • Defining the required Dispose() method • Having clients call Dispose() when they have finished with a class instance
Dispose • If Dispose() is called and freed the resources, you must not have the destructor do the same thing • You can suppress finialization by • GC.SuppressFinalize(this) • You should ensure that the resources are only freed once
Dispose using System; class Testing : IDisposable { bool is_disposed = false; protected virtual void Dispose() { if (!is_disposed) { // only dispose once! // perform cleanup for this object GC.SuppressFinalize(this); } this.is_disposed = true; } ~Testing( ) { Dispose(false); } }
The Using Statement • Since there is no way to guarantee that client code will call Dispose() , the using statement is provided using ( Font theFont = new Font( "Arial", 10.0f ) ) { // use theFont } // compiler will call Dispose on theFont • This guarantees Dispose() is called on theFont when the using block is exited
Parameter Passing • Normally, value parameters (int, char, etc.) are passed by value • A copy is made and passed to the method • The method might modify the copy • The copy is not returned and the original is left unchanged • We can modify this using the ref keyword to use pass by reference
Pass By Reference public add3(ref int n) { n = n + 3; } • Since a reference is used, the original value in the calling code is modified • There is no need to dereference anything as you would do with a C pointer
Out Parameters • Definite assignment requires that a parameter be initialized before it can be used • This means we have to initialize a variable before we pass it to a method, even though the method will set the value and never use it • We can use the out keyword to modify this behaviour
Out Parameters public void init(out int n) { n = 34; } • This code can be passed an uninitialized parameter • It can assign a value to the parameter and return it
Properties • Properties allow code to access the state of an object as if they were accessing a field directly • However, a property does not access a field • A special class method provides the access and controls what is determined • This simplifies the interface while prohibiting unrestricted access to class internals
Properties • Access to properties is provided accessors • A get accessor to return the value • A set accessor to set the value • These accessors are placed inside the property declaration • You can omit either the set or get accessor if they are not needed
Properties • Consider adding a Name property public class Person { string name; int age; public Person(string nm, int ag) {… } public string Name { get { return name; } set { name = value; } } }
Properties • The set accessor has no parameter • The value passed to it is called value • We can use the accessors like this: Person p = new Person(“Jane”, 29); Console.WriteLine(p.Name); p.Name = “Janie”;
Readonly Fields • Readonly fields can only be assigned • By initialization or • By a constructor • Sometimes, you want to create a public static constant but cannot initialize it • You can make it readonly so that it can be initialized by one of the constructors
Readonly Fields public class Color { public static readonly Color Black = new Color(0, 0, 0);public static readonly Color White = new Color(255, 255, 255); private byte red, green, blue; public Color(byte r, byte g, byte b) { red = r; green = g; blue = b; }} • We cannot initialize Black & White as constants because their values cannot be computed at compile time • Making them readonly has a similar effect to making them constants
Contents • Classes • Inheritance • Operator Overloading • Structs • Interfaces
Inheritance • C# supports single inheritance • Syntax: • public class ListBox: Window • Inherits all base class members • It can extend the base class by adding new members • It can override any method in the base class with a new method using the keyword new
Inheritance public class EmployedPerson: Person { float salary; … public float Salary { get {return salary;} } }
Base Class Construction • The base class must be constructed before the derived class • To do this, each constructor for the derived class must invoke the constructor for the base class • Constructors cannot be inherited, so each class must implement its own
Base Class Construction • If the base class has a default constructor which is accessible, it will be called automatically • If no default constructor is in the base class, another constructor must be called • A base class constructor is invoked with the base keyword
Base Class Construction public class EmployedPerson: Person { float salary; … public EmployedPerson(string name, int age, float salary): base(name, age) { this.salary = salary; } }
New Methods • When a derived class declares a method with the same name as a method in the base class it can • Hide the method in the base class • Polymorphically override the method in the base class • To hide the method in the base class, you must use the new keyword
New Methods • When you invoke a new method in the derived class • A reference to the derived type invokes the method in the derived class • If the derived instance is assigned to a base class reference variable, invoking the method with the base reference will invoke the base version of the method • * see Person example
public class PersonBase { … public string ClassName(){ return "PersonBase"; } } public class EmployedPerson: PersonBase { … public new string ClassName(){ return “EmployedPerson"; } } … PersonBase pb1, pb2; EmployedPerson ep1; pb1 = new PersonBase("Julie", 34); ep1 = new EmployedPerson("Betty", 28, 37000.0); pb2 = ep1; Console.WriteLine("pb1.ClassName() = {0}", pb1.ClassName()); Console.WriteLine("pb2.ClassName() = {0}", pb2.ClassName()); Console.WriteLine("ep1.ClassName() = {0}", ep1.ClassName()); New Methods PersonBase PersonBase EmployedPerson
Polymorphism • With true polymorphism, we can override methods and the compiler will always invoke the correct method • For this to work • The method in the base class must be virtual • The method in the derived class must be declared override
Polymorphism • System.Object declares the method ToString() as virtual • This is provided to convert every object to a string representation • We can override it in PersonBase by public override string ToString() { return name + ", " + age; }
Calling Base Class Methods • We want to override it again in the EmployedPerson class • This time, we want to call the version in the parent class using the base keyword public override string ToString() { return base.ToString() + ", " + salary; }
Versioning • Suppose we have classes • BaseClass • DerivedClass • Now, let’s add a virtual method to DerivedClass public class DerivedClass: BaseClass { public virtual void NewMethod() {…} }
Versioning • All is well • Now, pretend the author of BaseClass decides to provide the same method public class BaseClass { public virtual void NewMethod() {…} } • When this is compiled, a warning states that NewMethod() in DerivedClass hides the one in BaseClass
Versioning • The way this works is • To find a virtual method the compiler searches up the class chain for the first method marked virtual • For the derived class, this would be its version of the method • For the base class, its version would be used • The benefit of this is • A base class can be modified without breaking anything done in a derived class
Versioning • The warning states • Declare it new to hide the base method and eliminate the warning • Declare it override to override the base method • Or leave as is to hide with a new virtual method and still get the warning