2

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.

1 Answer 1

1

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.

5
  • 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
    Commented Jul 9, 2014 at 3:36
  • @donquixote Yes, you were on the right track with approach #2, Visitor is an established way of doing this.
    – paisanco
    Commented Jul 9, 2014 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
    Commented Jul 9, 2014 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
    Commented Jul 9, 2014 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
    Commented Jul 9, 2014 at 15:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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