W
werasm
I've read the following somewhere:
"Friendship is the strongest form of coupling there is. That is, you
introduce a high degree of dependency when you declare a friend, since
the friend becomes aware of the private details of a class. This means
that it is more difficult to change those private details, since there
are other things around that depend on them. It doesn't necessarily
indicate poor design, but a design that doesn't use friends may be
preferable to one that does."
Whilst fully agreeing with it, I suppose friendship could be a good
tool (enhance encapsulation) if an interface dictates who may use it.
Often an interface (or ABC) is realized by its client. It makes
natural sense that only its client should use it (and is often the
intent). This does not provide any additional coupling as the client
is already coupled to the ABC.
The simplest way to achieve this (only client code being allowed to
access a particular interface) is by friendship.
For instance:
//Commit only to be called by GenTblReader.
// Implementation commits data read (from IO)
// for use...
template <class RecordT>
class GenTblCommitIF
{
friend class GenTblReader<RecordT>;
virtual void commitTbl( const std::vector<RecordT> tbl ) throw() =
0;
};
//Responsible for commiting data read from disk
// to database... associated with GenTblCommitIF...
template <class RecordT>
class GenTblReader;
// Gives access to tables, and allows committing
// of new data read from IO
class Database
: GenTblCommitIF<RecordA>,
GenTblCommitIF<RecordB>,
GenTblCommitIF<RecordC>
{
private:
//Implement commits - only callable by correct class
};
While the private inheritance from GenTblCommitIF already
provides the necessary encapsulation to prevent erroneous
calling, it implies that Database needs to provide the
dependency to the applicable GenTblReader (or interface
client). If we use friendship to dictate who may use the
interface, the associating (or setting up of dependencies)
becomes much easier due to use not having to inherit
privately to promote encapsulation.
Does this make sense?
Declaring friends in interfaces (ABCs) promote encapsulation,
and reduce dependencies required to realise associations.
Regards,
Werner
"Friendship is the strongest form of coupling there is. That is, you
introduce a high degree of dependency when you declare a friend, since
the friend becomes aware of the private details of a class. This means
that it is more difficult to change those private details, since there
are other things around that depend on them. It doesn't necessarily
indicate poor design, but a design that doesn't use friends may be
preferable to one that does."
Whilst fully agreeing with it, I suppose friendship could be a good
tool (enhance encapsulation) if an interface dictates who may use it.
Often an interface (or ABC) is realized by its client. It makes
natural sense that only its client should use it (and is often the
intent). This does not provide any additional coupling as the client
is already coupled to the ABC.
The simplest way to achieve this (only client code being allowed to
access a particular interface) is by friendship.
For instance:
//Commit only to be called by GenTblReader.
// Implementation commits data read (from IO)
// for use...
template <class RecordT>
class GenTblCommitIF
{
friend class GenTblReader<RecordT>;
virtual void commitTbl( const std::vector<RecordT> tbl ) throw() =
0;
};
//Responsible for commiting data read from disk
// to database... associated with GenTblCommitIF...
template <class RecordT>
class GenTblReader;
// Gives access to tables, and allows committing
// of new data read from IO
class Database
: GenTblCommitIF<RecordA>,
GenTblCommitIF<RecordB>,
GenTblCommitIF<RecordC>
{
private:
//Implement commits - only callable by correct class
};
While the private inheritance from GenTblCommitIF already
provides the necessary encapsulation to prevent erroneous
calling, it implies that Database needs to provide the
dependency to the applicable GenTblReader (or interface
client). If we use friendship to dictate who may use the
interface, the associating (or setting up of dependencies)
becomes much easier due to use not having to inherit
privately to promote encapsulation.
Does this make sense?
Declaring friends in interfaces (ABCs) promote encapsulation,
and reduce dependencies required to realise associations.
Regards,
Werner