Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.php > #2184

Re: An overloading question

Message-Id <2975511.SPkdTlGXAF@PointedEars.de>
From Thomas 'PointedEars' Lahn <PointedEars@web.de>
Organization PointedEars Software (PES)
Date 2011-06-15 14:01 +0200
Subject Re: An overloading question
Newsgroups comp.lang.php
References <it83e6$u4e$1@dont-email.me>

Show all headers | View raw


sheldonlg wrote:

> I have a problem that I am wrestling with that should be so obvious and
> easy -- but it isn't.  I have a base class that has a method that calls
> another method in the base class with $this->thatOtherMethod.  I have
> another class that extends the base class and I want to have
> thatOtherMethod in the extended class override the one in the base
> class.  The calling method in the base class is called using and
> instance of the extended class pointing to that method.
> 
> Simply, here is an example:
> 
> A.class.php
> --------------------------
> <?php
> abstract class A {
>      public function b() {
>          $this->a();
>      }
>      protected function a() {
>          print 'In class A';
>      }
> }
> ?>
> 
> B.class.php
> ---------------------------
> <?php
> include_once 'A.class.php';
> class B extends A {
>      public function a() {
>          print 'In class B';
>      }
> }
> ?>
> 
> c.php
> ----------------------------
> <?php
>     include 'B.class.php';
>    $x = new B();
>    $x->b();
> ?>
> ----------------------------
> 
> I want it to print out "In class B", but it prints out "In class A".
> 
> I have looked over Google quite a bit and found nothing that helped.  I
> have tried making the methods public, protected, keep them both the same
> access, etc. and have had no luck.  Suggestions?

Yes.  Both your testing method and your posting leave much to be desired:

You should have avoided the `include's in the test code, thereby removing 
them from the equation and making it easier for people to test your code.  
They are deprecated for class loading anyway (at least by PEAR standards; 
use an autoloader instead).  [But if you must use includes in this context, 
you should use `require_once' instead.]

You should have added at least one output statement to *each* method, and 
between the global statements.  [You should have used `echo' instead of 
`print', since you are not using print's return value.]

You should not have named the method case-insensitively the same as the 
class, as that can make a constructor out of the method.  [But if that was 
your intention, you should have used exactly the same name – considering 
letter case – or (better since PHP 5) __construct.]

You should have said which PHP client (version, type) you have been testing 
with.

Finally, in retrospect of my results below, you should have been more 
precise as to the output you are getting.

Using a variant of your code that meets these criteria –

$ cat overloading.php 
<?php

abstract class A {
  public function b() {
    echo "A::b()\n";
    $this->a();
  }

  protected function a() {
    echo "A::a()\n";
  }
}

class B extends A {
  public function a() {
    echo "B::a()\n";
  }
}

echo "instantiation\n";
$x = new B();
echo "method call\n";
$x->b();

?>

–, I cannot confirm your observations here exactly:

$ php overloading.php 
instantiation
PHP Fatal error:  Call to protected A::a() from invalid context in 
****/overloading.php on line 21
PHP Stack trace:
PHP   1. {main}() ****/overloading.php:0

$ php --version
PHP 5.3.3-7+squeeze1 with Suhosin-Patch (cli) (built: Mar 18 2011 17:22:52) 
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
    with XCache v1.3.1, Copyright (c) 2005-2010, by mOo
    with Xdebug v2.1.0, Copyright (c) 2002-2010, by Derick Rethans
    with Suhosin v0.9.32.1, Copyright (c) 2007-2010, by SektionEins GmbH

But with the Apache 2.0 module of PHP 5.3.3-7+squeeze1 on the same computer, 
I am not getting this error for the same code; instead I get the following 
output (taken from the View Source window in the browser, Iceape 2.0.14):

instantiation
method call
A::b()
B::a()

If the visibility of A::a() is changed to `public' –

$ cat overloading2.php 
<?php

abstract class A {
  public function b() {
    echo "A::b()\n";
    $this->a();
  }

  public function a() {
    echo "A::a()\n";
  }
}

class B extends A {
  public function a() {
    echo "B::a()\n";
  }
}

echo "instantiation\n";
$x = new B();
echo "method call\n";
method call
A::b()
B::a()

$x->b();

?>

– I get the following with the CLI:

$ php overloading2.php 
instantiation
A::a()
method call
A::b()
B::a()

But with the Apache 2.0 module, I get:

instantiation
method call
A::b()
B::a()

A possible explanation for the CLI behavior is that, because B has no 
constructor, and A::b() is not inherited as constructor for B, but B is to 
be instantiated, the constructor of its superclass A, A::a(), is called 
instead (regardless whether that class is declared abstract, as it would not 
be instantiated).  This reasoning would be consistent with the fact that it 
is a fatal error when that constructor, A::a(), is not public.  [It 
certainly has *nothing* to do that PHP would not being able to call methods 
of instantiated classes properly, i.e. does not implement "virtual" methods.  
Although it does have OO deficiencies, PHP can do that well.  And *no* OOPL 
I know lets classes inherit constructors.]

If that applies, then the reason why you are not getting an error, and I am 
not getting an error with the Apache 2.0 module, could be that (perhaps 
through php.ini settings) the Apache 2.0 module enforces other (in my case: 
stricter) rules than the CLI, since the PHP versions are the same here.  
This reasoning would be consistent with the fact that, regardless whether 
A::a() is public or not, it is not called when using the Apache 2.0 module; 
we can assume B is considered to have an implicit empty constructor, 
B::__construct(), then (as A cannot be instantiated).  Then B::a() is called 
because A::b() can be and is inherited by B from A (it sort of becomes 
B::b() for instances of B), and A/B::b() calls B::a() accordingly, 
regardless whether A::a() it is public or not (as A::a() is not called in 
the first place).

[Suppose a php.ini setting is the reason for this difference, I would be 
grateful if someone pointed me to the relevant documentation.]

While that would explain why you are not getting an error, it would not 
explain why – as you stated – *only* A::a() would be called in any case.
A possible explanation for that would be that you were using a different, 
perhaps older, version of PHP.  In that case upgrading PHP might be a good
idea.


HTH

PointedEars
-- 
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee

Back to comp.lang.php | Previous | Next — Previous in thread | Find similar | Unroll thread


Thread

An overloading question sheldonlg <sheldonlg@thevillages.net> - 2011-06-14 12:49 -0400
  Re: An overloading question Denis McMahon <denis.m.f.mcmahon@gmail.com> - 2011-06-14 18:32 +0000
    Re: An overloading question sheldonlg <sheldonlg@thevillages.net> - 2011-06-14 18:27 -0400
      Re: An overloading question Jerry Stuckle <jstucklex@attglobal.net> - 2011-06-14 19:12 -0400
        Re: An overloading question sheldonlg <sheldonlg@thevillages.net> - 2011-06-14 19:43 -0400
          Re: An overloading question Jerry Stuckle <jstucklex@attglobal.net> - 2011-06-14 20:45 -0400
            Re: An overloading question sheldonlg <sheldonlg@thevillages.net> - 2011-06-14 21:58 -0400
              Re: An overloading question Jerry Stuckle <jstucklex@attglobal.net> - 2011-06-14 22:08 -0400
              Re: An overloading question Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2011-06-15 14:21 +0200
              Re: An overloading question sheldonlg <sheldonlg@thevillages.net> - 2011-06-15 12:55 -0400
        Re: An overloading question Michael Fesser <netizen@gmx.de> - 2011-06-15 18:04 +0200
          Re: An overloading question Jerry Stuckle <jstucklex@attglobal.net> - 2011-06-15 12:53 -0400
      Re: An overloading question Denis McMahon <denis.m.f.mcmahon@gmail.com> - 2011-06-15 03:41 +0000
      Re: An overloading question Michael Fesser <netizen@gmx.de> - 2011-06-15 18:02 +0200
  Re: An overloading question Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2011-06-15 14:01 +0200

csiph-web