Why is access and visibility mixed up in PHP?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Terje Slettebø

    Why is access and visibility mixed up in PHP?

    Well, as is customary when you're new to a group, you tend to post quite a
    bit, :) so here's one more. Some things I've been wondering about with PHP
    (5).

    Today, I worked on an implementation of a finite state machine. Unlike the
    pear::fsm, this one supports hierarchical states, and I intend to make it
    available, as well. It exists in both PHP 4 and 5 versions, but only the
    PHP5 version is relevant for this example. The base class defines some
    (virtual) functions that may be overridden in a derived class, but they are
    only called from the base class. My original code was as follows (I only
    quote the bare minimum needed for illustration):

    class fsm
    {
    ...
    public function process($signal )
    {
    // null_action() is called from here (unless another action function is
    specified for a transition)
    }

    private function null_action($fr om_state,$to_st ate)
    {
    }
    }

    class my_fsm extends fsm
    {
    private function null_action($fr om_state,$to_st ate)
    {
    echo "Transition from $from_state to $to_state";
    }
    }

    In C++ this would work just fine: As null_action() is called from fsm, and
    it's private in fsm, this works fine. It gets overridden in my_fsm, but
    being private in fsm, it can only be called there (not in my_fsm), which is
    as intended. This is because access and visibility are orthogonal concepts
    in C++: The access specifiers only specify who are allowed to access (as in
    calling, taking the address of, etc.) a function, but it doesn't affect
    overriding.

    The reason for this is as follows (from "The Design and Evolution of C++"):
    By not letting the access specifiers affect visibility (including
    overriding), changing the access specifiers of functions won't affect the
    program semantics.

    However, this is not so for PHP...

    The above won't work, or at least not work as intended: The function
    null_action() will only be visible in the class it's defined, and therefore
    the derived class version won't override the base class version. In order to
    get it to work, the access specifiers have to be changed to protected. This
    means that derived classes may also _call_ the function, something that is
    not desired. This means I can't enforce this design constraint of having
    this function private.

    Why is it done like this?

    Regards,

    Terje


  • Tim Van Wassenhove

    #2
    Re: Why is access and visibility mixed up in PHP?

    ["Followup-To:" header set to comp.lang.php.]
    On 2005-01-22, Terje Slettebø <tslettebo@hotm ail.com> wrote:

    [snip code]
    [color=blue]
    > The above won't work, or at least not work as intended: The function
    > null_action() will only be visible in the class it's defined, and therefore
    > the derived class version won't override the base class version. In order to
    > get it to work, the access specifiers have to be changed to protected. This
    > means that derived classes may also _call_ the function, something that is
    > not desired. This means I can't enforce this design constraint of having
    > this function private.[/color]

    Actually, you can have the constraint. But it acts as expected in PHP
    and not the way you would like it to act.
    [color=blue]
    > Why is it done like this?[/color]

    I think you can better ask this on a php-internals ml.
    My guess is that this is done because OOP in PHP5 seems to have been inspired by Java.
    (Would also explain why we don't have friend visibility)


    --
    Met vriendelijke groeten,
    Tim Van Wassenhove <http://www.timvw.info>

    Comment

    • Terje Slettebø

      #3
      Re: Why is access and visibility mixed up in PHP?

      "Tim Van Wassenhove" <timvw@users.so urceforge.net> wrote in message
      news:35g9v0F4kf a5kU3@individua l.net...[color=blue]
      > ["Followup-To:" header set to comp.lang.php.]
      > On 2005-01-22, Terje Slettebø <tslettebo@hotm ail.com> wrote:
      >[color=green]
      > > The above won't work, or at least not work as intended: The function
      > > null_action() will only be visible in the class it's defined, and[/color][/color]
      therefore[color=blue][color=green]
      > > the derived class version won't override the base class version. In[/color][/color]
      order to[color=blue][color=green]
      > > get it to work, the access specifiers have to be changed to protected.[/color][/color]
      This[color=blue][color=green]
      > > means that derived classes may also _call_ the function, something that[/color][/color]
      is[color=blue][color=green]
      > > not desired. This means I can't enforce this design constraint of having
      > > this function private.[/color]
      >
      > Actually, you can have the constraint.[/color]

      No. The constraint was that it should be possible to override the function
      in a derived class, but not to call it, there. Anyway, from my experience
      with the FSM, it seems PHP behaves sufficiently different from C++ (and
      Java, actually) in this context, that the issue is kind of moot. To
      illustrate:

      class base
      {
      public function g()
      {
      $this->f(); // Succeeds!
      }
      }

      class derived extends base
      {
      protected function f() { echo "f()"; }
      }

      $object=new derived();

      $object->g(); // Prints "f()"

      IOW, it's possible to call a derived class function from the base class,
      even if it's not defined in the base class (this is rather unlike Java, but
      actually very useful for the FSM :) ), as long as the actual object being
      used is of class derived.
      [color=blue]
      > But it acts as expected in PHP and not the way you would like it to act.[/color]

      It seems that "what is expected" may be a tad subjective. :) For a C++
      programmer, the way I described (being able to override, but not call, a
      private virtual function) makes complete sense, at least to those that know
      that access (being able to call) and inheritance/visibility (being able to
      override) are orthogonal in C++.

      For those interested, here's an article about it (C++):
      http://www.gotw.ca/publications/mill18.htm However, the advice to prefer
      public nonvirtual functions, delegating to private virtual functions, is not
      something that is generally agreed upon (but also has nothing to do with my
      example, as it doesn't do this).

      However, I guess the Java/PHP way of doing it is reasonable, as well.

      Regards,

      Terje


      Comment

      Working...