Let's say you have

  • class Car with Car->tune() and Car->drive()
  • class CarDriver
  • class CarMechanic

Each CarDriver and CarMechanic object has a reference/pointer to a Car object. The CarDriver object will call $this->car->drive(), the CarMechanic object will call $this->car->tune().

The question is, how can I prevent a CarDriver from calling $car->tune() ?

There are probably two approaches:

  1. Language level: Using access modifiers like public/private/protected, and then either abuse inheritance or use more exotic language features like a C++ "friend class".
  2. Composition: Split the car into a CarFrontend and CarBackend, or create a DriverCarWrapper, which exposes only the drive() method.
    This seems like a good idea, but it will likely introduce clutter and code duplication, which might outweigh the benefits of access control. Especially if there are many methods that should be accessible to the car driver.

Are there any other solutions that I missed?

Background: My real-world use case is in PHP, but I am asking this as a cross-language question.


What you want to do sounds like Double Dispatch.

Basically, you want to dispatch the call to the Car class based on whether the object interacting with the Car is a CarDriver or CarMechanic.

One popular way of implementing this in object oriented languages is with the Visitor pattern.

In your case, you would create DriverVisitor and MechanicVisitor classes that the Driver and Mechanic classes call respectively. These visitors would in turn invoke the appropriate methods on the Car class that are allowable for the Driver and Mechanic roles.

  • So in essence the DriverVisitor is just a wrapper for the Car, as suggested in the second approach in the question? I think I can imagine the implementation, but still need to read the pattern definitions .. – donquixote Jul 9 '14 at 3:36
  • @donquixote Yes, you were on the right track with approach #2, Visitor is an established way of doing this. – paisanco Jul 9 '14 at 3:38
  • And it does introduce some clutter and code duplication, at least signature duplication. Similar to a Proxy class. Whenever I add a new method I now need to change two places. Any idea how to avoid that, or at least reduce the pain? – donquixote Jul 9 '14 at 3:38
  • @donquixote yes in effect your Vistor classes act as proxies between the Car and the Driver and Mechanic. It's isolating the pain to the Visitors. The pain isolation would become more apparent if you had to iterate over many Cars. – paisanco Jul 9 '14 at 3:41
  • I am not really convinced that what we are doing here matches the definition of a Visitor pattern. Also see stackoverflow.com/questions/350404/… – donquixote Jul 9 '14 at 15:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.