delegation

T

Tony Johansson

Hello!

What does it mean with delegation and can you give me one example.

//Tony
 
V

Victor Bazarov

Tony said:
What does it mean with delegation and can you give me one example.


class Calculator {
public:
int calculate(int,int);
};

class NeedsSomeCalculation {
Calculator calc;
public:
explicit NeedsSomeCalculation(Calculator const& c) : calc(c) {}
void do_something(int a, int b) {
int result = calc.calculate(a,b); // delegation
}
};

Calculator global_calculator;

int main() {
NeedsSomeCalculation obj(global_calculator);
obj.do_something(1,2);
}

In the example above, instead of performing some calculation in the
object itself, the NeedSomeCalculation instance is made to rely on
another object (of another class) to do some work for it. That's
delegation.

Often delegation is used when something is implemented in terms of
something else:

class PhoneNumber : private std::string { // notice 'private'
public:
static bool isvalidchar(char);

PhoneNumber(const char*); // will verify the format and
// throw if invalid
void append(char c) {
if (isvalidchar(c))
std::string::append(1, c); // delegation!
}

size_t length() const {
return std::string::length(); // delegation!
}
};

'PhoneNumber' is implemented in terms of 'std::string', but cannot
be used anywhere where 'std::string' can. Using OO definitions we
say that 'PhoneNumber' and 'std::string' _do_not_ have the "is-a"
relationship.

V
 
M

Markus Dehmann

Tony said:
What does it mean with delegation and can you give me one example.

Delegation is often an alternative to inheritance.

Suppose you want a special set class that basically behaves like std::set,
and provides the usual functions insert(element), find(), end(). But you
want that insert(element) inserts a *modified* version of the element, e.g.
all-uppercase if the elements are string.

You have two possibilities: inheritance or delegation.

Inheritance:
Make a subclass my_set of std::set and override the insert(element) function
so that it inserts a modified version of the element. (Maybe that's not
even possible if std::set::insert is not virtual).

class my_set : public std::set {
// ...
};


Delegation would be the alternative:
Create you own class my_set, with the member functions insert(element),
find(), end(). It also has a member variable std::set theSet. For the
find() and end() function, you just delegate the calls to theSet! For the
insert(element) function, you modify the element and call
theSet.insert(modifiedElement):

Basically, it looks like this:

class my_set {
public:
// delegate call:
std::set<T>::iterator end(){
return theSet.end();
}
// ... other delegate functions: insert, find
private:
std::set theSet; // delegate all calls to this set object!
};


Delegation is often better than inheritance, for several reasons: You
provide only the functions that are needed, here: insert, find, end. If you
*inherit* you inherit a bunch of other functions whose behavior you don't
know and can't control. std::set might contain other insert functions that
you haven't thought of. If you inherit from std::set your class would have
all these functions, and they do *not* insert a modified version of the
element, as you intended.

Even worse, std::set might change its API (although unlikely for STL
classes, but certainly likely for other classes that you might want to
subclass), adding some different insert() functions, and your subclass
would suddenly be broken! Because those new insert functions would not
insert *modified* versions of the element, which was the point of your
my_set class.

There are more reasons why delegation is better than inheritance, but I
can't remember off the top of my head.
 
A

Andrew McDonagh

Markus said:
Tony Johansson wrote:




Delegation is often an alternative to inheritance.

Suppose you want a special set class that basically behaves like std::set,
and provides the usual functions insert(element), find(), end(). But you
want that insert(element) inserts a *modified* version of the element, e.g.
all-uppercase if the elements are string.

You have two possibilities: inheritance or delegation.

Inheritance:
Make a subclass my_set of std::set and override the insert(element) function
so that it inserts a modified version of the element. (Maybe that's not
even possible if std::set::insert is not virtual).

class my_set : public std::set {
// ...
};


Delegation would be the alternative:
Create you own class my_set, with the member functions insert(element),
find(), end(). It also has a member variable std::set theSet. For the
find() and end() function, you just delegate the calls to theSet! For the
insert(element) function, you modify the element and call
theSet.insert(modifiedElement):

Basically, it looks like this:

class my_set {
public:
// delegate call:
std::set<T>::iterator end(){
return theSet.end();
}
// ... other delegate functions: insert, find
private:
std::set theSet; // delegate all calls to this set object!
};


Delegation is often better than inheritance, for several reasons: You
provide only the functions that are needed, here: insert, find, end. If you
*inherit* you inherit a bunch of other functions whose behavior you don't
know and can't control. std::set might contain other insert functions that
you haven't thought of. If you inherit from std::set your class would have
all these functions, and they do *not* insert a modified version of the
element, as you intended.

Even worse, std::set might change its API (although unlikely for STL
classes, but certainly likely for other classes that you might want to
subclass), adding some different insert() functions, and your subclass
would suddenly be broken! Because those new insert functions would not
insert *modified* versions of the element, which was the point of your
my_set class.

There are more reasons why delegation is better than inheritance, but I
can't remember off the top of my head.

All good points...

one other is that we can have dynamic relationships between the class
and its delegate(s) - i.e. we can change who the delegate is at runtime.
Whereas inheritance is a static relationship.

The delegate can also be of a concrete type that we don't know or didn't
know at compile time - so long as all delegates support the same interface.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,204
Messages
2,571,064
Members
47,672
Latest member
svaraho

Latest Threads

Top