Click here to Skip to main content
15,881,757 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

I know friend concept is a no no in OOP design.
But, sometimes there are cases where you'd allow access of certain methods of a class by certain friend classes only given the classes are very inter-twined to each other.

For example, CGridCtrl's friend class is CGridCellBase. To understand, which example I am talking about, please have a look at the article by Chris Maunder related to CGridCtrl in code project.

So, if I were to develop something similar in a language which doesn't support the friend keyword, how would I make sure, CGridCtrl's certain methods are only accessible by CGridCellBase class only?
Posted
Updated 13-Oct-10 22:14pm
v4

 
Share this answer
 
Comments
Mukit, Ataul 14-Oct-10 4:08am    
Thanks very much for your answer which gave me some insight about java and friend. But sorry for being stupid. Actually my question was not stated properly. I thought java didn't support the concept of friend at all (silly me). What I really wanted to ask was, what is the design pattern to address the problem of exposing few methods to only certain classes.
CPallini 14-Oct-10 5:00am    
AFAIK there isn't such a design pattern. Why don't you like the 'package workaround'?
Mukit, Ataul 14-Oct-10 5:26am    
Say, I am not using java, rather C# or some other language which doesn't have the friend feature..
CPallini 14-Oct-10 6:49am    
You cannot do that at compile time.
As you can see the friend is declared for a certain type. This automatically closes this friend for other types. Like in the link below:

http://www.cprogramming.com/tutorial/friends.html[^]

To guarantee the same for certain methods you can define friend functions that have access to certain data, like:

http://www.exforsys.com/tutorials/c-plus-plus/c-plus-plus-friend-functions.html[^]

The same can be done for operators. Like this:
http://www.devarticles.com/c/a/Cplusplus/C-plus-Tricks-of-the-Trade:-Friend-Functions/2/[^]

Please study the above links very good and maybe try to find extra information about it. Sometimes it's hard to see how this friend construction does the trick. It's therefore considered a no no with a good reason because if you do not understand it completely, the code is unsafe and a big mess. (and c++ errors aren't the most kind ones to understand).

Good luck!
 
Share this answer
 
Comments
Mukit, Ataul 14-Oct-10 4:11am    
Actually my question was not stated properly. I thought java didn't support the concept of friend at all (silly me). What I really wanted to ask was, what is the design pattern to address the problem of exposing few methods to only certain classes
E.F. Nijboer 14-Oct-10 4:14am    
Ah well, I see you got the answer you needed as well :)
Mukit, Ataul 14-Oct-10 4:25am    
Nope, not yet.. my question wasn't state properly and I rephrased the question .. so could you please have a look at the question again and suggest a solution please?
E.F. Nijboer 14-Oct-10 6:51am    
Aha, but the vote would imply otherwise, but okay.
I think the pattern you are looking for is proxy.
wikipedia - "Provide a surrogate or placeholder for another object to control access to it."
Mukit, Ataul 14-Oct-10 7:09am    
Thanks, but probably not possible in compile time like Pallini said.. But thanx very much, I'd be looking into it.. Btw can you give an example or a reference site which deals with this problem?
Adapter or Bridge will do the trick. Exactly how you do it depends on what you're trying to adapt or bridge. If you're trying to just expose a few methods and they've got the right interface already then bridge works pretty well. If you want to expose some methods and their signatures are not quite the right shape then use an Adapter.

As Eric said proxy will work as well - although that's usually regarded as a way of exporting an interface over some "hostile" or non-native way of calling it. It's like a bridge but across an external communication mechanism.

Anyway:

- bridge introduces another interface with just the methods in you want to export from the object. You then derive your implementation from the interface and pass a reference to that interface to the consuming object

- adapter introduces a concrete class with the interface you want to consume. You implement that interface using the class to be adapted. You can introduce an interface class to really isolate the adapted class from the consuming class - whether you do that or not is really a matter of taste and how much knowledge of the implementation you're willing to leak across the consumer/adapter boundary

With bridge you'll have to change the class you're bridging to. With adapter you won't. Generally I'd say what you want is an adapter BUT a bridge will help introduce a new concept into your code which will make it easier to factor.

Er, sorry, that's really stream of consciousness isn't it? Please shout if I can (or rather if you'd like me to) clarify anything.

Cheers,

Ash

PS: Most of my experience of this sort of thing has been with C++ so my comments might not be appropriate in general OO terms.

PPS: In response to the comment below, here's what I mean about how to use a bridge. Say I've got a class, A, that uses part of the interface of object of class B:

class B
{
    public:
        void b_a();
        void b_b();
        void b_c();
};

class A
{
    public:
        void a_a( B &b )
        {
            b.b_a();
            b.b_c();
        }
};

so you can see that A doesn't use B::b_b(). Effectively it doesn't need some part of the interface of B.

So to restrict what bits of B A uses we can define a new interface (the bridge solution):

class I
{
    public:
        virtual void b_a() = 0;
        virtual void b_c() = 0;
};


derive B from I:

class B : public I
{
    public:
        void b_a();
        void b_b();
        void b_c();
};

and convert A to use I, not B:

class A
{
    public:
        void a_a( I &i )
        {
            i.b_a();
            i.b_c();
        }
};

So everytime you call the A::a_a you can still pass it a B, but A can't use B::b_b() as it's not part of the interface.

Using an adapter is similar, I can add that if there's any milage.
 
Share this answer
 
v3
Comments
E.F. Nijboer 14-Oct-10 8:29am    
An adapter is used to make classes compatible, which is not directly meant to restrict access. A bridge adds a second layer of abstraction but is very close to the adapter. In this case I don't believe that the class wouldn't fit, but it would expose to much functionality. Also, I must admit that even the proxy I suggested isn't completely the fit with the actual definition. In most cases inheritance leads to an increase of functionality but in this case specific narrowing is requested.
Aescleal 14-Oct-10 10:31am    
How would a bridge "expose too much functionality?"

I've added a chunk to the end of my answer.
As mentioned in the comment to Aescleal, I believe what you want to do is narrow the functionality of a class for certain classes. The problem with that is that at runtime (or design time) there is no easy way to to track down who is the caller from which class. And even if you could, it wouldn't become a pretty sight.

I think the most simple way of handling it, is to define certain interfaces with different methods exposed.
Simply create several interfaces like:
public interface Reader { public char read(); }
public interface Writer { public char writer(); }
public interface Opener { public char opener(); }
public interface Closer { public char closer(); }

public class SimpleFile implements Reader, Writer, Opener, Closer {
   ...
}


This way you can simply give each class that uses it an interface of the SimpleFile class with appropriate methods exposed. You could also use extends to combine the interfaces so it is possible to have some overlap.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900