OOP - materials in ppt

advertisement
Object Oriented Programming
Basic techniques
Exceptions and exception proof code
Templates and generic programming
Class vs. object
A class is a programming language construct that is used
to group related instance variables and methods
Object is an instance of a class
Class is a type of object
Car
class Car {
id
int id;
Accelerate()
.....
public:
void Accelerate();
myauto : Car
};
otherauto : Car
Car myauto, otherauto;
Classes vs. structures
C++:
Classes are very similar to structures
Access - class content is private by default
Class can contain virtual methods
C#:
Classes are reference types, structure are
value types
Java:
No structures exists
Encapsulation, hermetization
A class content may be accessible for class exterior or
not
Possible accessors: public, private, protected, internal
(C#)
Fields should be not accessible from outside of class
class Car {
int id;
public:
void Accelerate();
};
Car myauto;
myauto.Accelerate(); //myauto.id = 3;
Class content
Methods
 plain
 constructors
 operators
Attributes
class Car {
int id;
public:
Car (int newId);
void Accelerate();
operator ==(Car &);
};
Car myauto(3);
myauto.Accelerate();
if (myauto==otherauto) ....;
Properties (java, c#, managed c++)
Constructor
Constructor is called
when object is created
There can be many
versions of constructors
The default (nonparameters) constructors
should be defined only if
necessary to avoid
improperly initialised
objects
class Car {
int id;
public:
Car (int newId);
Car (Car model);
void Accelerate();
};
Car myauto(3);
Car mycopy(myauto);
myauto.Accelerate();
Destructor
Destructor is called when
object is destroyed
There can be only one
destructor
The destructor should be
defined only if some
clean-up is necessary
In Java, C# - only in
extraordinary cases –
when managed code
deals with unmanaged
resources
class Car {
int dbconnection;
public:
Car (int newId);
~Car () {
}
Close(dbconnection);
};
{
}
Car myauto(3);
....
Derivation
Super class (i.e. base class) means less
specialized class, class with less
components
Sub class (i.e. derived class) means
specialised class or the special case
of class
class Truck : public Car {
int capacity;
public:
void Unload();
};
Truck v;
v.Accelerate();
Car
Accelerate()
Decelerate()
Truck
capacity
Unload()
Aggregation
Car
Class may contain many fields. fields
may be objects of other classes
motor:Engine
class Engine {
public:
void Start();
void Stop();
};
class Car {
Engine motor;
public:
void Accelerate();
void Decelerate();
};
Decelerate()
Engine
Start()
Stop()
Accelerate()
Derivation vs. aggregation
Sub class (i.e. derived Engine
class) is a special case Start()
of super class. Egg.:
Stop()
Truck is a special case
of Car
External class uses
some functions from
internal class but is not
similar to it. Egg.:Car
is not a special case of
Engine.
Car
motor:Engine
Accelerate()
Decelerate()
Truck
capacity
Unload()
Derrivation introduces closer relation than agregation
so if not sure - better prefere aggregation
Object vs. class again
attributes, methods related to object
static – means attributes, methods related to class i.e.
common for all the object of this class
class Car {
Engine motor;
static int cnt=0;
public:
static GetCount() { return cnt; }
void Accelerate();
void Decelerate();
};
C++: Car::GetCount() or mycar.GetCount();
C#: Car.GetCount()
Java: Car.GetCount() or mycar.GetCount();
Derivation again
Container
Capacity
Car
Load()
Accelerate()
Unload()
Decelerate()
C++: Multiple class
derivation
C#, Java: Multiple
interface derivation
Truck
capacity
Unload()
Basic techniques
Concepts of interface
Interface – defines a set of functions/properties that
should be delivered (implemented) by a class (Java,
C#, managed c++)
Abstract class – class that implements not all of the
expected functions
//C# code
interface IVehicle {
public:
void Accelerate();
void Decelerate();
};
class Car : IVehicle { .... };
IVehicle v = new Car; v.Accelerate();
Single vs multiple derivation
C++: derivation from multiple class is
allowed
Engine
Start()
Stop()
Car
Boat
motor:Engine
Engine
motor:Engine
Accelerate()
Start()
SailFaster()
Decelerate()
Stop()
SailSlower()
Amphibious
Single vs multiple derivation
C#, Java: derivation from (implementation
of) multiple interfaces is allowed
ICar
IBoat
Accelerate()
SailFaster()
Decelerate()
SailSlower()
Amphibious
Derivation forbidden?
Why?
- to not modify the class by client,
- to not extend, change etc.
C#: sealed
Java: final
Overloading
... multiple functions with same name but
different sets of arguments
class Car {
public:
void Accelerate(int x);
void Accelerate(double x);
void Accelerate(Car &c);
};
Overriding
... redefinition of function in sub class
class Car {
public:
void Accelerate(); // 1st
};
class Truck {
public:
void Accelerate(); // 2nd
};
Car mycar;
mycar.Accelerate(); // 1st or 2nd ???
Truck mytruck;
mytruck.Accelerate(); // 1st or 2nd ???
Polymorphism
def. Allowing a single definition to be used
with different types of data
Types of polymorphism. :
subtype polymorphism
parametric polymorphism = generic
programming (i.e. templates, generic
types)
Subtype polymorphismCar
C++ virtual is necessary in base class, in
derived identical functions will be
Accelerate()
automatically treat as virtual (but IT IS
RECOMMENDED to write virtual
specificator again
C#: virtual in base and overriden in derived
Truck
is required
Java: every overriding is virtual
Accelerate()
Uscases:
1) using pointer or reference and call (C#, and Java
Note in C#, Java we have always references
2) using anothing (ie. object in c++ as well) and call to
function that calls another, virtual function
Subtype polymorphism – case 1
class Car {
public: virtual void Accelerate(); // 1st
Car
Accelerate()
};
class Truck {
public: virtual void Accelerate(); // 2nd
};
Truck
Car mycar; mycar.Accelerate(); // ???
Accelerate()
Truck mytruck; mytruck.Accelerate(); // ???
Truck * mytruckPtr = new Truck; mytruckPtr->Accelerate(); //???
Car * mycarPtr = new Car; mycarPtr->Accelerate(); //???
delete mycar;
mycarPtr = new Truck; mycar->Accelerate(); //???
Subtype polymorphism – case 2
class Car {
public: virtual void Accelerate(); // 1st
virtual void Test() { Accelerate(); }
Car
Accelerate()
Test()
};
class Truck {
public: virtual void Accelerate(); // 2nd
Truck
};
Accelerate()
Car mycar; mycar.Test(); // ???
Truck mytruck; mytruck.Test(); // ???
Please note that in fact:
....
virtual void Test() { this->Accelerate(); }
Parametric polymorphism
class Car {};
class Plane {};
class Dispatcher {
LoadTo(Car & c);
LoadTo(Plane & p);
}
Car c;
Plane p;
Dispatcher d;
d.LoadTo(p);
d.LoadTo(c);
This mechanism is extended in templates
Namespaces
Limiting of scope of identifiers to avoid
conflicts between different modules etc.
namespace A { float x; };
namespace B { int y; int x;
namespace A { float z=x;
using A::z;
z = B::y;
using namespace A;
using namespace B;
x=y; // ??
};
};
Exception and exception proof code
Exception
Throwing of exception causes


making a copy of exception object
cleaning of stack:
 execution of destructors of local objects
 removing of local objects

return of execution control to the range
above
Throwing of exception
Throwing of exception
C#, Java: throw new Exception;
C++: throw Exception;
throw „abc”;
Please note that the object created by „new”
should be destroyed by programmer. So
however the construction „throw new...” is
syntactically corrected it is used hardly ever
consider catch(...)
Catching of exception
try {
....
}
catch(Exception1 e) {...}
catch(Exception2 e) {...}
catch(Exception e) {...}
There is executed the first and only the first matched
clause catch, if any fits the current scope will be leaved
If Exception2 is super class of Exception1 the clause for
Exception2 should be placed after clause for Exception1
Releasing of resources
What kind of resources we should take care
about:





memory (for C++)
system objects
GDI objects
db connections etc.
other not managed resources
The objects pointed above should be released
by programmer
Cleaning code in
managed languages
The finishing code should be repeated for a normal
finish of try code and every catch clause.
To avoid of multiplication of code there is available in
C#, Java and managed C++ the finally clause.
try {
....
}
finally { releasing_of_resources ; }
catch(Exception1 e) {...}
catch(Exception2 e) {...}
catch(Exception e) {...}
Releasing of resources
What kind of resources we should take care
about:





memory (for C++)
system objects
GDI objects
db connections etc.
other not managed resources
The objects pointed above should be released
by programmer
Releasing resources in C++
try {
// there may be the inner try blocks
....
// releasing of resources
}
catch(...)
{
// releasing of resources
throw;
}
Issues:
●
●
releasing code has to be written in two places
what about return instruction?
Destructor should be called in
automate way
class wrapper {
public:
Resource m_resource;
wrapper(Resource &resource);
~wrapper() {
//releasing of resource
}
};
{
wrapper w (new car);
working_with (w.m_resource); // throw Exception;
working_with (w.m_resource);
}
Wrappers – some issues
Unnatural way of usage resource:
 overriding of operators *,->
Handling of wrapper copying
 reference counting (reference semantics)
 resource copying (value semantics)
 forbidding of copying
Dedicated wrapper for particular resource type:
 template using
What about unfinished objects
class Picture { };
class Sound {};
class Document {
Picture *m_picture;
Sound *m_sound;
Document() {
m_picture = new Picture(); // can be raised exception ?
m_sound = new Sound(); // can be raised exception ?
}
~Document(); // delete m_picture, m_sound
};
Document doc;
Constructor – more problems
Document() {
m_picture = new Picture();
m_sound = new Sound();
}
...
Document doc;
Order of operations:

allocation of Picture (1)

constructor of Picture (2)

allocation of sound (3)

constructor of sound (4)
What about exception in 1,2,3,4
Destructor is called only for properly created and constructed
objects so destructor of Document wont be called in case of
exception in constructor.
Constructor – more problems
Document() : m_picture (NULL), m_sound(NULL){
try {
m_picture = new Picture();
m_sound = new Sound();
}
catch(...)
{
delete m_picture; // legal for m_picture==NULL
delete m_sound;
}
}
Problem:
The cleaning code has to be placed in destructor as well
Safe solution
class Picture { };
class Sound {};
class Document {
wrapper<Picture> m_picture;
wrapper<Sound> m_sound;
Document() :
m_picture (new Picture()) ,
m_sound(new Sound()) { }
~ Document()
{ };
};
....
Document doc;
What about destructor ?
Document() :
m_picture (new Picture()) ,
m_sound(new Sound()) 1
{}
~ Document()
{ }; 2
1
During construction of sound the exception was raised
( but what if the destructor of picture raises the second
exception)
2 During removing of Document object (because of
exception somewhere in the code) the destructor of
Picture raises the new exception )
Destructor cannot...
• raising of a new exception when a previous
one is still not handled properly is forbidden
so
• DESTRUCTOR is not expected to throw a new
exception in any circumstances!!!
Templates
Templates motivation
Many same functions (i.e. same names) with different
types – means overriding
Many same functions (i.e. same names) with different
types, but identical logic
int max(int a, int b) { return a>b ? a : b; }
long max(long, long) ....
float max(float, float) ....
double max(double, double) ....
C++: using macros
#define max(a,b) ((a)>(b) ? (a) : (b) )
x = max(3,5);
Drawbacks:
hard debugging
surprises..., egg.: max(x++, y)
Function template C++
Definition:
template <class T>
T max(T a, T b) { return a > b ? a : b; }
Usage:
max(3, 5);
max(2.5, 5.5);
max(2, 1.5);
// int czy float ?
Specialisation:
char* max(char*a, char*b)
{return strcmp(a,b)>0 ? a : b; }
max("xxx","yyy");
Please note that compiler requires the body of template when
used so usually templates are defined in .h file
Function template - properties
Global
Parameter(s) might be types
Not every parameters of template function have to be
depend on template parameter
template <class T>
T gen(T, int cnt) { .... } ;
Type of template instance is recognised basing on
parameters
long m = max(1, 2)
int m = max(1, 2)
When a function to call is determined there are
considered:
1.
2.
normal functions (specialised template functions) if ideal
matching is possible
templates and possible template instances
Template - matching
1.
2.
When type of template is determined there are
considered:
specialised function
templates and possible template instances
Only ideal fit of parameters is possible - consider
max(1, 2.5)
New compilers allows trivial conversions
D* to B*, D& to B&,
T to const & T,
T& to const T &, T* to const T*
When function address is taken the type of desired
pointer (to function) is considered
int (fun*)(int, int);
Template - parameters
Int x,y;
xxx(x,y);
template <class T>
T xxx(T, T&) { .... } ;
template <class T, class Z>
T xxx(T, Z&) { .... } ;
yyy(x,&y);
template <class T, class Z>
T xxx(T, Z*) { .... } ;
template <class T, class Z>
T xxx(T, Z) { .... } ;

F. template – returned type
Templates have to differ not only with returned type
(why?)
template <class T>
T * gen(int a) { return new T[a]; }
int * ti = gen(3); double * td = gen(3);
Solution: additional parameter
template <class T>
T * gen(T, int a) { return new T[a]; }
int * = gen(2, 100);
Class template
template <class T>
class vector {
T * m_array;
public:
vector () { m_array = new T[DEFSIZE]; }
vector (long size) { m_array = new T[size]; }
~vector () { delete m_array; }
void put(T element, long pos);
{m_array[pos] = element; }
T get(long pos) { return m_array [pos]; }
T& operator[](long pos) { return m_array[pos]; }
};
vector<int> vi, vii(100);
typedef vector<int> VECTORINT;
VECTORINT vi1, vii1(100);
Template instance
vs class instance
template <class TINDX, class TELEM>
class vector {
TELEM * m_array;
public:
vector (TINDX size);
};
Template instance (means class):
vector<long, int>
class instance (means object) :
vi(100);
Template & methods
template <class T>
class vector {
T * m_array;
public:
vector (long size);
T& operator[](long pos) { return m_array[pos]; }
};
template <class T>
T& vector<T>:: operator[](long pos)
{ return m_array[pos]; }
template <class T>
vector<T>::vector(long size) : m_array(new T[size]) {}
Functions might be defined in class body or not
Specialisation in class templates
Specialised class
class vector <char> {
.......
};
specialised method
long & vector <long>::operator[](long pos) { .... }
Specialised attribute
vector<long>::refcount = -1;
Static, enum
template <class T>
class vector {
T * m_array;
static long refcount = 0; // new compilers only....
enum ETyp { t1, t2, t3 };
};
// older compilers require
// explicite declaration
template <class T>
long vector<T>::refcount = 0;
vector<long>::ETyp vaiable;
Static attribute is „common” for particular template
instance
Functions and classes
template <class T>
class vector {
T * m_array;
public:
vector (long size);
T& operator[](long pos) { return m_array[pos]; }
};
template <class T>
Creator <class T>
vector<T> fun (T, int cnt)
{ return vector<t>(cnt); }
Instead of global function template it is worth to
consider static function in vector class template...
Aggregation?
template <class T>
class vector {
T * m_array;
public:
vector (long size);
T& operator[](long pos) { return m_array[pos]; }
};
template <class T>
class tester
{
T m_element;
vector<T> m_vector;
...
}
template <class T, class Z>
class tester
{
T m_element;
vector<Z> m_vector;
...
}
Inner class?
template <class T>
class vector {
public:
class helper { ... };
private:
 T * m_array;
public:
 vector (long size);
};
vector<int> v(5);
vector<int>::helper h;
Only the new C++ compilers
Template methods of class?
class Container {
...
public:
template <class T>
 void assign(T element) { ... };
...
};
template <class ELEM> class Container {
...
void assign (const ELEM element) { ... }
public:
template <class T>
 void assign(T element) { ... }
};
Only the new C++ compilers
Template in template?
template <class ELEM>
class vector {
public:
 template <class T>
 class adaptor { ... };
private:
 ELEM * m_array;
public:
 vector (long size);
};
vector<int> v(5);
vector<int>::adaptor<MyClass> h;
Only the new compilers
Class template parameters
template <class TINDX, class TELEM>
class vector {
TELEM * m_array;
public:
vector (TINDX size);
};
vector<long, int> vi(100);
Class template parameters ...
template <long size, class TELEM>
class vector {
TELEM * m_array;
public:
vector () { m_array = new T[size]; }
...
};
vector<100, int> vi;
thank to using the number code can be
determined in compilation time
Default parameters
template <class TELEM, class INDEX=long>
class vector {
TELEM * m_array;
public:
vector () { m_array = new T[size]; }
TELEM get(INDEX i ) { .... }
...
};
vector<int> vi;
vector<int,short> vismall;
Templates vs. deriving
Class
Instance of template (== class)
Template
Class can derive from class, instance of template
Instance of template can derive from class,
instance of template
class neither instance of template can not derive
from template
Template can derive from class, instance of
template or template
Use cases
Class from class - Nothing new :-)
Class from instance of template – modified template
behaviour
class VA : public vector <char> { ... };
Instance of template from class/ Instance of template
specialisation of template on the class level
class vector <char> : public vectorChar : { ... };
class vector <char> : public array<char> : { ... };
Use cases part 2
Deriving template from class/instance
Reduction of code overhead
Hiding the code against template end user
(programmes have access to template source code but
a base class is delivered as binaries)
template <class T>
class vector <T> : public vectorBase { ... };
Deriving template from template
Extension of template logic
template <class T>
class vector <T> : public container<T> { ... };
Explicit zero initialization
Problem: uniformed code for zeroing user types
and built-in types
int x = int();
A a = A();
template <class T>
void fun(T t)
{
T local = T();
};
C++: Template instances
When a template is used for any type the compiler
creates the separate code for this template instance
E.g. the following cases
vector<int>
vector<double>
vector<car>
imply generation (during compilation) 3 different
classes (with all the member functions)
C# - generic types
Availiable since Framework 2.0 (VS2005)
public class
Cont<T> {
private T field;
public void Store(T arg) {
field = arg;
}
}
Cont<int> c = new Cont<int>();
c.Store(10);
Cont<string> cs = new Cont<string>();
cs.Store(„abc”);
C#: Generics
public class
Cont<T> : where T : IToDo{
private T field;
public void Store(T arg) {
field = arg;
field.DoSomething();
}
}
public interface IToDo {
void DoSomething();
}
Cont <MyClass> c = new Cont <MyClass>();
c.Store(new MyClass("ABC"));
For unbounded types it is only possible to convert to System.Object
and to compare to null value
C#: Constraints on T parameter
where T: struct - argument must be a value type
where T : class - argument must be a reference type, including
any class, interface, delegate, or array type
where T : new() - the type argument must have a public
parameterless constructor
where T : <base class name> - the type argument must be or
derive from the specified base class.
where T : <interface name> - the type argument must be or
implement the specified interface. Multiple interface
constraints can be specified. The constraining interface can
also be generic.
where T : U - the type argument supplied for T must be or derive
from the argument supplied for U. This is called a naked type
constraint.
C#: Generic interfaces
public Interface
IPrinter <T> {
void Print(T t);
}
class IntPrinter : IPrinter < int> {
public void Print (int w) { ... }
}
class GenericPrinter <T> :IPrinter<T> {
public void Print (T w) { ... }
}
C#: Generic methods
static void Swap<T>(ref T lhs, ref T rhs)
{
T temp;
temp = lhs; lhs = rhs; rhs = temp;
}
public static void TestSwap()
{
int a = 1;
int b = 2;
Swap<int>(ref a, ref b);
Swap(ref a, ref b);
System.Console.WriteLine(a + " " + b);
}
C#: Generic methods
In comparing to C++
the separate instances for all the value types are
generated
a common instance for all the reference types is
used
Java: generic types
public interface Iterator<E> {
E next();
boolean hasNext();
}
public interface List<E> {
void add(E x);
Iterator<E> iterator();
}
List<Integer> myIntList = new LinkedList<Integer>();
myIntList.add(new Integer(0));
Integer x = myIntList.iterator().next();
Java: wildcards
void printCollection(Collection<?> c) {
for (Object e : c) {
System.out.println(e);
}
}
Java: wildcards with bounding
public abstract class Shape { public abstract void
draw(Canvas c);
}
public class Circle extends Shape { ... }
public class Rectangle extends Shape {... }
// shapes only -> List<Shape>
public void drawAll(List<Shape> shapes) {
for (Shape s: shapes) {
s.draw(this);
}
}
// shapes and derrived List<Rectangle>
public void drawAll(List<? extends Shape> shapes) { ... }
Download