Programming in C# Classes and Structs

advertisement
Programming in C#
Object-Oriented
CSE 668
Prof. Roger Crawfis
Key Object-Oriented Concepts
Objects, instances and classes
 Identity



Every instance has a unique identity,
regardless of its data
Encapsulation
Data and function are packaged together
 Information hiding
 An object is an abstraction


User should NOT know implementation details
Key Object-Oriented Concepts

Interfaces



Types


A well-defined contract
A set of function members
An object has a type, which specifies its interfaces
and their implementations
Inheritance

Types are arranged in a hierarchy


Base/derived, superclass/subclass
Interface vs. implementation inheritance
Key Object-Oriented Concepts

Polymorphism


The ability to use an object without knowing its
precise type
Three main kinds of polymorphism




Inheritance
Interfaces
Reflection
Dependencies


For reuse and to facilitate development, systems
should be loosely coupled
Dependencies should be minimized
Programming in C#
Inheritance and Polymorphism
CSE 668
Prof. Roger Crawfis
C# Classes

Classes are used to accomplish:


Modularity: Scope for global (static) methods
Blueprints for generating objects or instances:


Per instance data and method signatures
Classes support


Data encapsulation - private data and
implementation.
Inheritance - code reuse
Inheritance




Inheritance allows a software developer to derive a
new class from an existing one.
The existing class is called the parent, super, or base
class.
The derived class is called a child or subclass.
The child inherits characteristics of the parent.


The child has special rights to the parents methods
and data.



Methods and data defined for the parent class.
Public access like any one else
Protected access available only to child classes (and their
descendants).
The child has its own unique behaviors and data.
Inheritance


Inheritance
relationships are often
shown graphically in a
class diagram, with
the arrow pointing to
the parent class.
Inheritance should
create an is-a
relationship, meaning
the child is a more
specific version of the
parent.
Animal
Bird
Examples: Base Classes and Derived Classes
Ba se c la ss
Derived c la sses
Student
GraduateStudent
UndergraduateStudent
Shape
Circle
Triangle
Rectangle
Loan
CarLoan
HomeImprovementLoan
MortgageLoan
Employee
FacultyMember
StaffMember
Account
CheckingAccount
SavingsAccount
Declaring a Derived Class

Define a new class DerivedClass which
extends BaseClass
class BaseClass
{
// class contents
}
class DerivedClass : BaseClass
{
// class contents
}
Controlling Inheritance


A child class inherits the methods and data defined for
the parent class; however, whether a data or method
member of a parent class is accessible in the child
class depends on the visibility modifier of a member.
Variables and methods declared with private visibility
are not accessible in the child class


However, a private data member defined in the parent class is
still part of the state of a derived class.
Variables and methods declared with public visibility
are accessible; but public variables violate our goal of
encapsulation
 There is a third visibility modifier that helps in
inheritance situations: protected.
The protected Modifier

Variables and methods
declared with protected
visibility in a parent class
are only accessible by a
child class or any class
derived from that class
Book
# pages : int
+ GetNumberOfPages() : void
Dictionary
- definition : int
+ PrintDefinitionMessage() : void
+ public
- private
# protected
Single Inheritance
Some languages, e.g., C++, allow
Multiple inheritance, which allows a class
to be derived from two or more classes,
inheriting the members of all parents.
 C# and Java support single inheritance,
meaning that a derived class can have
only one parent class.

Overriding Methods

A child class can override the definition of
an inherited method in favor of its own
 That is, a child can redefine a method that it
inherits from its parent
 The new method must have the same
signature as the parent's method, but can
have a different implementation.
 The type of the object executing the
method determines which version of the
method is invoked.
Class Hierarchies

A child class of one parent can be the
parent of another child, forming a class
Animal
hierarchy
Reptile
Snake
Lizard
Bird
Parrot
Mammal
Horse
Bat
Class Hierarchies
CommunityMember
Employee
Faculty
Professor
Instructor
Student
Staff
Under
Alumnus
Graduate
Class Hierarchies
Shape
TwoDimensionalShape
Circle
Square
Triangle
ThreeDimensionalShape
Sphere
Cube
Cylinder
Class Hierarchies

An inherited member is continually
passed down the line


Inheritance is transitive.
Good class design puts all common
features as high in the hierarchy as is
reasonable. Avoids redundant code.
References and Inheritance

An object reference can refer to an object of its
class, or to an object of any class derived from
it by inheritance.
 For example, if the Holiday class is used to
derive a child class called Christmas, then a
Holiday reference can be used to point to a
Christmas object.
Holiday day;
day = new Holiday();
…
day = new Christmas();
Dynamic Binding
A polymorphic reference is one which
can refer to different types of objects at
different times. It morphs!
 The type of the actual instance, not the
declared type, determines which method
is invoked.
 Polymorphic references are therefore
resolved at run-time, not during
compilation.


This is called dynamic binding.
Dynamic Binding



Suppose the Holiday class has a method
called Celebrate, and the Christmas
class redefines it (overrides it).
Now consider the following invocation:
day.Celebrate();
If day refers to a Holiday object, it
invokes the Holiday version of
Celebrate; if it refers to a Christmas
object, it invokes the Christmas version
Overriding Methods

C# requires that all class definitions
communicate clearly their intentions.
 The keywords virtual, override and new
provide this communication.
 If a base class method is going to be
overridden it should be declared virtual.
 A derived class would then indicate that it
indeed does override the method with the
override keyword.
Overriding Methods
If a derived class wishes to hide a
method in the parent class, it will use the
new keyword.
 This should be avoided.

Overloading vs. Overriding



Overloading deals with
multiple methods in
the same class with
the same name but
different signatures
Overloading lets you
define a similar
operation in different
ways for different data
Example:
int foo(string[] bar);
int foo(int bar1, float a);



Overriding deals with
two methods, one in a
parent class and one in
a child class, that have
the same signature
Overriding lets you
define a similar
operation in different
ways for different object
types
Example:
class Base {
public virtual int foo() {} }
class Derived {
public override int foo() {}}
Polymorphism via Inheritance
StaffMember
# name : string
# address : string
# phone : string
+ ToString() : string
+ Pay() : double
Employee
Volunteer
# socialSecurityNumber : String
# payRate : double
+ ToString() : string
+ Pay() : double
+ Pay() : double
Executive
- bonus : double
+ AwardBonus(execBonus : double) : void
+ Pay() : double
Hourly
- hoursWorked : int
+ AddHours(moreHours : int) : void
+ ToString() : string
+ Pay() : double
Widening and Narrowing

Assigning an object to an ancestor reference
is considered to be a widening conversion,
and can be performed by simple assignment
Holiday day = new Christmas();

Assigning an ancestor object to a reference
can also be done, but it is considered to be a
narrowing conversion and must be done with
a cast:
Christmas christ = new Christmas();
Holiday day = christ;
Christmas christ2 = (Christmas)day;
Widening and Narrowing

Widening conversions are most common.

Used in polymorphism.

Note: Do not be confused with the term
widening or narrowing and memory. Many
books use short to long as a widening
conversion. A long just happens to take-up
more memory in this case.
 More accurately, think in terms of sets:


The set of animals is greater than the set of parrots.
The set of whole numbers between 0-65535
(ushort) is greater (wider) than those from 0-255
(byte).
Type Unification

Everything in C# inherits from object



Similar to Java except includes value types.
Value types are still light-weight and
handled specially by the CLI/CLR.
This provides a single base type for all
instances of all types.

Called Type Unification
The System.Object Class

All classes in C# are derived from the Object class

if a class is not explicitly defined to be the child of an existing
class, it is a direct descendant of the Object class
The Object class is therefore the ultimate root of all class
hierarchies.
 The Object class defines methods that will be shared by
all objects in C#, e.g.,





ToString: converts an object to a string representation
Equals: checks if two objects are the same
GetType: returns the type of a type of object
A class can override a method defined in Object to have a
different behavior, e.g.,

String class overrides the Equals method to compare the
content of two strings
Programming in C#
Properties
CSE 668
Prof. Roger Crawfis
Properties

Typical pattern for accessing fields.
private int x;
public int GetX();
public void SetX(int newVal);

Elevated into the language:
private int count;
public int Count {
get { return count; }
set { count = value; }
}

Typically there is a backing-store, but not
always.
Properties

Using a property is more like using a
public field than calling a function:
FooClass foo;
int count = foo.Count; // calls get
int count = foo.count; // compile error

The compiler automatically generates
the routine or in-lines the code.
Properties
Properties can be used in interfaces
 Can have three types of a property



read-write, read-only, write-only
More important with WPF and
declarative programming.
// read-only property declaration
//
in an interface.
int ID { get; };
Automatic Properties
C# 3.0 added a shortcut version for the
common case (or rapid prototyping)
where my get and set just read and
wrote to a backing store data element.
 Avoids having to declare the backing
store. The compiler generates it for you
implicitly.

public decimal CurrentPrice { get; set; }
Programming in C#
Interfaces
CSE 668
Prof. Roger Crawfis
Interfaces

An interface defines a contract




An interface is a type
Contain definitions for methods, properties,
indexers, and/or events
Any class or struct implementing an interface must
support all parts of the contract
Interfaces provide no implementation

When a class or struct implements an interface it
must provide the implementations
Interfaces

Interfaces provide polymorphism
Many classes and structs may implement
a particular interface.
 Hence, can use an instance of any one of
these to satisfy a contract.


Interfaces may be implemented either:
Implicitly – contain methods with the same
signature. The most common approach.
 Explicitly – contain methods that are
explicitly labeled to handle the contract.

Interfaces Example
public interface IDelete {
void Delete();
}
public class TextBox : IDelete {
public void Delete() { ... }
}
public class Car : IDelete {
public void Delete() { ... }
}
TextBox tb = new TextBox();
tb.Delete();
Car c = new Car();
iDel = c;
iDel.Delete();
Explicit Interfaces

Explicit interfaces require the user of the
class to explicitly indicate that it wants to
use the contract.

Note: Most books seem to describe this as a
namespace conflict solution problem. If that is
the problem you have an extremely poor
software design. The differences and when
you want to use them are more subtle.
Explicit Interfaces
namespace OhioState.CSE494R.InterfaceTest
{
public interface IDelete
{
void Delete();
}
public class TextBox : IDelete
{
#region IDelete Members
void IDelete.Delete()
{ ... }
#endregion
}
}
TextBox tb = new TextBox();
tb.Delete(); // compile error
iDel = tb;
iDel.Delete();
Explicit Interfaces
The ReadOnlyCollection<T> class is a
good example of using an explicit
interface implementation to hide the
methods of the IList<T> interface that
allow modifications to the collection.
 Calling Add() will result in a compiler
error if the type is ReadOnlyCollection.
 Calling IList.Add() will throw a run-time
exception .

Interfaces Multiple Inheritance
Classes and structs can inherit from
multiple interfaces
 Interfaces can inherit from multiple
interfaces

interface IControl {
void Paint();
}
interface IListBox: IControl {
void SetItems(string[] items);
}
interface IComboBox: ITextBox, IListBox {
}
Programming in C#
Structs
CSE 668
Prof. Roger Crawfis
Classes vs. Structs

Both are user-defined types
 Both can implement multiple interfaces
 Both can contain

Data


Functions


Fields, constants, events, arrays
Methods, properties, indexers, operators, constructors
Type definitions

Classes, structs, enums, interfaces, delegates
Classes vs. Structs
Class
Struct
Reference type
Value type
Can inherit from any
non-sealed reference
type
No inheritance
(inherits only from
System.ValueType)
Can have a destructor
No destructor
Can have user-defined
No user-defined
parameterless
parameterless constructor
constructor
C# Structs vs. C++ Structs

Very different from C++ struct
C++ Struct
C# Struct
Same as C++ class, but all
members are public
User-defined value type
Can be allocated on the heap,
on the stack or as a member
(can be used as value or reference)
Always allocated on the stack or
in-lined as a member field
Members are always public
Members can be public,
internal or private
Class Definition
public class Car : Vehicle {
public enum Make { GM, Honda, BMW }
private Make make;
private string vid;
private Point location;
Car(Make make, string vid, Point loc) {
this.make = make;
this.vid = vid;
this.location = loc;
}
Car c =
new Car(Car.Make.BMW,
“JF3559QT98”,
new Point(3,7));
c.Drive();
public void Drive() {
Console.WriteLine(“vroom”); }
}
Struct Definition
public struct Point {
private int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int X { get { return x; }
set { x = value; } }
public int Y { get { return y; }
set { y = value; } }
}
Point p = new Point(2,5);
p.X += 100;
int px = p.X;
// px = 102
Programming in C#
Modifiers
CSE 668
Prof. Roger Crawfis
Static vs. Instance Members

By default, members are per instance
Each instance gets its own fields
 Methods apply to a specific instance


Static members are per type
Static methods can’t access instance data
 No this variable in static methods

Singleton Design Pattern
public class SoundManager {
private static SoundManager instance;
public static SoundManager Instance {
get { return instance; }
}
private static
SoundManager() {
Static property
– returns
reference to an
instance
= newthe
SoundManager();
instance of a SoundManager
}
private SoundManager() {
…
}
}
Access Modifiers
Access modifiers specify who can use a
type or a member
 Access modifiers control encapsulation
 Class members can be public, private,
protected, internal, or protected internal
 Struct members can be public, private or
internal

Access Modifiers
If the access
modifier is
Then a member defined in type
T and assembly A is accessible
public
to everyone
private
within T only
protected
to T or types derived from T
internal
to types within A
protected
internal
to T or types derived from T
-or- to types within A
Access Defaults
You should always explicitly mark what
access you want.
 Class definitions default to internal.
 Member fields, methods and events
default to private for classes
 Member methods and events for
interfaces must be public, so you can not
specify an access modifier for interfaces.

Abstract Classes
An abstract class can not be instantiated
 Intended to be used as a base class
 May contain abstract and non-abstract
function members
 A pure abstract class has no
implementation (only abstract members)
and is similar to an interface.

Sealed Classes
A sealed class is one that cannot be
used as a base class.
 Sealed classes can not be abstract
 All structs are implicitly sealed
 Prevents unintended derivation
 Allows for code optimization


Virtual function calls may be able to be
resolved at compile-time
Programming in C#
Class Internals
CSE 668
Prof. Roger Crawfis
this

The this keyword is a predefined variable
available in non-static function members

Used to access data and function members
unambiguously
public class Person {
private string name;
public Person(string name) {
this.name = name;
}
public void Introduce(Person p) {
if (p != this)
Console.WriteLine(“Hi, I’m “ + name);
}
}
base

The base keyword can be used to
access class members that are hidden
by similarly named members of the
current class
public class Shape {
private int x, y;
public override string ToString()
return "x=" + x + ",y=" + y;
{
}
}
internal class Circle : Shape {
private int r;
public override string ToString() {
return base.ToString() + ",r=" + r;
}
}
Constants

A constant is a data member that is
evaluated at compile-time and is
implicitly static (per type)

e.g. Math.PI
public class MyClass {
public const string version = “1.0.0”;
public const string s1 = “abc” + “def”;
public const int i3 = 1 + 2;
public const double PI_I3 = i3 * Math.PI;
public const double s = Math.Sin(Math.PI);
...
}
//ERROR
Fields
A field or member variable holds data for
a class or struct
 Can hold:

A built-in value type
 A class instance (a reference)
 A struct instance (actual data)
 An array of class or struct instances
(an array is actually a reference)
 An event

Readonly Fields

Similar to a const, but is initialized at
run-time in its declaration or in a constructor


Once initialized, it cannot be modified
Differs from a constant

Initialized at run-time (vs. compile-time)


Don’t have to re-compile clients
Can be static or per-instance
public class MyClass {
public static readonly double d1 = Math.Sin(Math.PI);
public readonly string s1;
public MyClass(string s) { s1 = s; } }
Methods

All code executes in a method
Constructors, destructors and operators are
special types of methods
 Properties and indexers are implemented
with get/set methods

Methods have argument lists
 Methods contain statements
 Methods can return a value

Virtual Methods

Methods may be virtual or non-virtual (default)
 Non-virtual methods are not polymorphic
 Abstract methods are implicitly virtual.
internal class Foo {
public void DoSomething(int i) {
...
}
}
Foo f = new Foo();
f.DoSomething(6);
Virtual Methods
public class Shape {
public virtual void Draw() { ... }
}
internal class Box : Shape {
public override void Draw() { ... }
}
internal class Sphere : Shape {
public override void Draw() { ... }
}
protected void HandleShape(Shape s)
{
s.Draw();
...
HandleShape(new Box());
}
HandleShape(new Sphere());
HandleShape(new Shape());
Abstract Methods
An abstract method is virtual and has no
implementation
 Must belong to an abstract class
 Used as placeholders or handles where
specific behaviors can be defined.
 Supports the Template design pattern.

Abstract Methods
public abstract class Shape {
public abstract void Draw();
}
internal class Box : Shape {
public override void Draw() { ... }
}
internal class Sphere : Shape {
public override void Draw() { ... }
}
private void HandleShape(Shape s) {
s.Draw();
...
}
HandleShape(new Box());
HandleShape(new Sphere());
HandleShape(new Shape()); // Error!
Method Versioning
Must explicitly use override or new
keywords to specify versioning intent
 Avoids accidental overriding
 Methods are non-virtual by default
 C++ and Java produce fragile base
classes – cannot specify versioning
intent

Programming in C#
Constructors
CSE 668
Prof. Roger Crawfis
Constructors





Instance constructors are special methods that
are called when a class or struct is instantiated
Performs custom initialization
Can be overloaded
If a class doesn’t define any constructors, an
implicit parameterless constructor is created
Cannot create a parameterless constructor for
a struct

All fields initialized to zero/null
Constructor Initializers
One constructor can call another with a
constructor initializer
 Use the this keyword. The called
constructor will execute before the body
of the current constructor.

internal class B {
private int h;
public B() : this(12) { }
public B(int h) { this.h = h; }
}
Constructor Initializers

The base keyword is also used to control
the constructors in a class hierarchy:
public class Volunteer : Employee
{
public Volunteer( string name )
: base(name)
{
}
}
Constructor Initializers
internal class B {
private int h;
public B() : this(12) { }
public B(int h) { this.h = h; }
}
internal class D : B {
private int i;
public D() : this(24) { }
public D(int i) { this.i = i; }
public D(int i, int h) : base(h) { this.i = i; }
}
Static Constructors





A static constructor lets you create initialization
code that is called once for the class
Guaranteed to be executed before the first
instance of a class or struct is created and
before any static member of the class or struct
is accessed
No other guarantees on execution order
Only one static constructor per type
Must be parameterless
Singleton Design Pattern
public class SoundManager {
private static SoundManager instance;
public static SoundManager Instance {
get { return instance; }
Static constructor
– called once per type
}
– not user-callable (private)
private static SoundManager() {
instance = new SoundManager();
}
private SoundManager() {
…
Instance constructor
}
– marked private
}
Destructors

A destructor is a method that is called before
an instance is garbage collected
 Used to clean up any resources held by the
instance, do bookkeeping, etc.
 Only classes, not structs can have destructors
 Also called Finalizers.
internal class Foo {
private ~Foo() {
Console.WriteLine(“Destroyed {0}”, this);
}
}
Destructors





Unlike C++, C# destructors are nondeterministic
They are not guaranteed to be called at a
specific time
They are guaranteed to be called before
shutdown
You can not directly call the destructor
Slows down the garbage collection if you
define one, so don’t unless you have to.
Dispose Design Pattern
Use the using statement and the
IDisposable interface to achieve
deterministic clean-up of unmanaged
resources.
 The destructor optionally calls a public
Dispose method, that is also usercallable.

Programming in C#
Operators
CSE 668
Prof. Roger Crawfis
Operator Overloading
User-defined operators
 Must be a static method

internal class Car {
private string vid;
public static bool operator ==(Car x, Car y) {
return x.vid == y.vid;
}
}
Operator Overloading

Overloadable unary operators
+
-
!
~
true
false
++
--
 Overloadable
binary operators
+
-
*
/
!
~
%
&
|
^
==
!=
<<
>>
<
>
<=
>=
Operator Overloading
No overloading for member access,
method invocation, assignment
operators, nor these operators: sizeof,
new, is, as, typeof, checked, unchecked,
&&, ||, and ?:
 Overloading a binary operator (e.g. *)
implicitly overloads the corresponding
assignment operator (e.g. *=)

Operator Overloading
public struct Vector {
private int x, y;
public Vector(int x,int y) { this.x = x; this.y = y; }
public static Vector operator +(Vector a, Vector b) {
return new Vector(a.x + b.x, a.y + b.y);
}
public static Vector operator*(Vector a, int scale) {
return new Vector(a.x * scale, a.y * scale);
}
public static Vector operator*(int scale, Vector a) {
return a * scale;
}
}
Conversion Operators

Can also specify user-defined explicit
and implicit conversions
internal class Note {
private int value;
// Convert to hertz – no loss of precision
public static implicit operator double(Note x) {
return ...;
}
// Convert to nearest note
public static explicit operator Note(double x) {
return ...;
}
Note n = (Note)442.578;
}
double d = n;
The is Operator

The is operator is used to dynamically
test if the run-time type of an object is
compatible with a given type
private static void DoSomething(object o) {
if (o is Car)
((Car)o).Drive();
}
The as Operator
The as operator tries to convert a
variable to a specified type; if no such
conversion is possible the result is null
 More efficient than using is operator


Can test and convert in one operation
private static void DoSomething(object o) {
Car c = o as Car;
if (c != null) c.Drive();
}
Download