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


Groups > comp.lang.php > #2150 > unrolled thread

An overloading question

Started bysheldonlg <sheldonlg@thevillages.net>
First post2011-06-14 12:49 -0400
Last post2011-06-15 14:01 +0200
Articles 15 — 5 participants

Back to article view | Back to comp.lang.php


Contents

  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

#2150 — An overloading question

Fromsheldonlg <sheldonlg@thevillages.net>
Date2011-06-14 12:49 -0400
SubjectAn overloading question
Message-ID<it83e6$u4e$1@dont-email.me>
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?

-- 
Shelly

[toc] | [next] | [standalone]


#2153

FromDenis McMahon <denis.m.f.mcmahon@gmail.com>
Date2011-06-14 18:32 +0000
Message-ID<4df7a92f$0$12468$bed64819@gradwell.net>
In reply to#2150
On Tue, 14 Jun 2011 12:49:11 -0400, 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?

I think A->a() is being used as a constructor for the base class when you 
instantiate the extended class.

This might (or might not) be causing confusion as to what's happening.

This code:

<?php

abstract class A {

     public function x() {
         print "x() In class A\n";
         $this->y();
     }

     public function y() {
         print "y() In class A\n";
     }

     public function a() {
         print "a() In class A\n";
     }

}

class B extends A {

     public function y() {
         print "y() In class B\n";
     }

}

print "instantiate\n";

$x = new B();

print "call function\n";

$x->x();

?>

gives:

instantiate
a() In class A
call function
x() In class A
y() In class B

Not sure, though, if that solves your problem or not?

Rgds

Denis McMahon

[toc] | [prev] | [next] | [standalone]


#2162

Fromsheldonlg <sheldonlg@thevillages.net>
Date2011-06-14 18:27 -0400
Message-ID<it8n87$7rj$1@dont-email.me>
In reply to#2153
On 6/14/2011 2:32 PM, Denis McMahon wrote:
> On Tue, 14 Jun 2011 12:49:11 -0400, 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?
>
> I think A->a() is being used as a constructor for the base class when you
> instantiate the extended class.
>
> This might (or might not) be causing confusion as to what's happening.
>
> This code:
>
> <?php
>
> abstract class A {
>
>       public function x() {
>           print "x() In class A\n";
>           $this->y();
>       }
>
>       public function y() {
>           print "y() In class A\n";
>       }
>
>       public function a() {
>           print "a() In class A\n";
>       }
>
> }
>
> class B extends A {
>
>       public function y() {
>           print "y() In class B\n";
>       }
>
> }
>
> print "instantiate\n";
>
> $x = new B();
>
> print "call function\n";
>
> $x->x();
>
> ?>
>
> gives:
>
> instantiate
> a() In class A
> call function
> x() In class A
> y() In class B
>
> Not sure, though, if that solves your problem or not?
>
> Rgds
>
> Denis McMahon

I modified B to give it an explicit constructor.  It still didn't work. 
  Why did your example print out that last line.  It was never called. 
Why did it use it as a constructor?  That doesn't seem to make sense.

-- 
Shelly

[toc] | [prev] | [next] | [standalone]


#2165

FromJerry Stuckle <jstucklex@attglobal.net>
Date2011-06-14 19:12 -0400
Message-ID<it8ps7$su3$1@dont-email.me>
In reply to#2162
On 6/14/2011 6:27 PM, sheldonlg wrote:
> On 6/14/2011 2:32 PM, Denis McMahon wrote:
>> On Tue, 14 Jun 2011 12:49:11 -0400, 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?
>>
>> I think A->a() is being used as a constructor for the base class when you
>> instantiate the extended class.
>>
>> This might (or might not) be causing confusion as to what's happening.
>>
>> This code:
>>
>> <?php
>>
>> abstract class A {
>>
>> public function x() {
>> print "x() In class A\n";
>> $this->y();
>> }
>>
>> public function y() {
>> print "y() In class A\n";
>> }
>>
>> public function a() {
>> print "a() In class A\n";
>> }
>>
>> }
>>
>> class B extends A {
>>
>> public function y() {
>> print "y() In class B\n";
>> }
>>
>> }
>>
>> print "instantiate\n";
>>
>> $x = new B();
>>
>> print "call function\n";
>>
>> $x->x();
>>
>> ?>
>>
>> gives:
>>
>> instantiate
>> a() In class A
>> call function
>> x() In class A
>> y() In class B
>>
>> Not sure, though, if that solves your problem or not?
>>
>> Rgds
>>
>> Denis McMahon
>
> I modified B to give it an explicit constructor. It still didn't work.
> Why did your example print out that last line. It was never called. Why
> did it use it as a constructor? That doesn't seem to make sense.
>

Unfortunately, PHP doesn't really implement OO constructs very well - in 
fact they to a pretty piss poor job of it.  One of the problems is with 
virtual functions, as you found.  A good OO language would work like you 
want, but PHP doesn't - the constructor for A will, in this case, only 
call a function in A.  In C++, Smalltalk, Java and most other OO 
languages, you could define y() as virtual and the constructor for A 
would call the function y() in B.

But if you created a constructor in B properly, it should call B:y(). 
I'd suggest checking your code again - you might have made a mistake.

-- 
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex@attglobal.net
==================

[toc] | [prev] | [next] | [standalone]


#2166

Fromsheldonlg <sheldonlg@thevillages.net>
Date2011-06-14 19:43 -0400
Message-ID<it8rmh$6is$1@dont-email.me>
In reply to#2165
On 6/14/2011 7:12 PM, Jerry Stuckle wrote:
> On 6/14/2011 6:27 PM, sheldonlg wrote:
>> On 6/14/2011 2:32 PM, Denis McMahon wrote:
>>> On Tue, 14 Jun 2011 12:49:11 -0400, 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?
>>>

> Unfortunately, PHP doesn't really implement OO constructs very well - in
> fact they to a pretty piss poor job of it. One of the problems is with
> virtual functions, as you found. A good OO language would work like you
> want, but PHP doesn't - the constructor for A will, in this case, only
> call a function in A. In C++, Smalltalk, Java and most other OO
> languages, you could define y() as virtual and the constructor for A
> would call the function y() in B.

I could define the method in A as abstract (and the class).  It would 
then require that it be implemented in B.  However, I am not the only 
application using A, and so doing that would require all the other apps 
to also implement it in an extended class.  That is a no-no and is one 
of the reasons for using B in the first place.

>
> But if you created a constructor in B properly, it should call B:y().

I did create a constructor in B properly.

> I'd suggest checking your code again - you might have made a mistake.
>

No mistakes that I could find.

-- 
Shelly

[toc] | [prev] | [next] | [standalone]


#2167

FromJerry Stuckle <jstucklex@attglobal.net>
Date2011-06-14 20:45 -0400
Message-ID<it8vca$nt9$2@dont-email.me>
In reply to#2166
On 6/14/2011 7:43 PM, sheldonlg wrote:
> On 6/14/2011 7:12 PM, Jerry Stuckle wrote:
>> On 6/14/2011 6:27 PM, sheldonlg wrote:
>>> On 6/14/2011 2:32 PM, Denis McMahon wrote:
>>>> On Tue, 14 Jun 2011 12:49:11 -0400, 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?
>>>>
>
>> Unfortunately, PHP doesn't really implement OO constructs very well - in
>> fact they to a pretty piss poor job of it. One of the problems is with
>> virtual functions, as you found. A good OO language would work like you
>> want, but PHP doesn't - the constructor for A will, in this case, only
>> call a function in A. In C++, Smalltalk, Java and most other OO
>> languages, you could define y() as virtual and the constructor for A
>> would call the function y() in B.
>
> I could define the method in A as abstract (and the class). It would
> then require that it be implemented in B. However, I am not the only
> application using A, and so doing that would require all the other apps
> to also implement it in an extended class. That is a no-no and is one of
> the reasons for using B in the first place.
>
>>
>> But if you created a constructor in B properly, it should call B:y().
>
> I did create a constructor in B properly.
>
>> I'd suggest checking your code again - you might have made a mistake.
>>
>
> No mistakes that I could find.
>

Id you created it properly, then the constructor in B should be calling 
b::y().

I still suggest you have a mistake in your code.

-- 
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex@attglobal.net
==================

[toc] | [prev] | [next] | [standalone]


#2168

Fromsheldonlg <sheldonlg@thevillages.net>
Date2011-06-14 21:58 -0400
Message-ID<it93k1$dkn$1@dont-email.me>
In reply to#2167
On 6/14/2011 8:45 PM, Jerry Stuckle wrote:
> Id you created it properly, then the constructor in B should be calling
> b::y().
>
> I still suggest you have a mistake in your code.

No, both constructors are there but are empty.

Now here is the really weird thing.  I decided to experiment with a 
simplified example and so copied the entire files into a test area via a 
copy/paste.  I then eliminated all methods that were not called, 
eliminated all includes that were no longer needed in the classes, and 
modified the important routines to only do the printing and the one 
calling routine in the class to only call the prescribed method and not 
do any other work.  So, besides the constructors (which were empty) the 
base class had two methods and the overload class had one (with the name 
as the final method invoked in the base class).  The only typing I did 
was putting print statements in the final invoked methods to identify 
which one was doing the output.

I expected the same result as the I had been getting.  However, what 
happened was that the output was from the overloaded method, not the 
base method.

Now I am totally baffled.

-- 
Shelly

[toc] | [prev] | [next] | [standalone]


#2169

FromJerry Stuckle <jstucklex@attglobal.net>
Date2011-06-14 22:08 -0400
Message-ID<it946e$gij$1@dont-email.me>
In reply to#2168
On 6/14/2011 9:58 PM, sheldonlg wrote:
> On 6/14/2011 8:45 PM, Jerry Stuckle wrote:
>> Id you created it properly, then the constructor in B should be calling
>> b::y().
>>
>> I still suggest you have a mistake in your code.
>
> No, both constructors are there but are empty.
>
> Now here is the really weird thing. I decided to experiment with a
> simplified example and so copied the entire files into a test area via a
> copy/paste. I then eliminated all methods that were not called,
> eliminated all includes that were no longer needed in the classes, and
> modified the important routines to only do the printing and the one
> calling routine in the class to only call the prescribed method and not
> do any other work. So, besides the constructors (which were empty) the
> base class had two methods and the overload class had one (with the name
> as the final method invoked in the base class). The only typing I did
> was putting print statements in the final invoked methods to identify
> which one was doing the output.
>
> I expected the same result as the I had been getting. However, what
> happened was that the output was from the overloaded method, not the
> base method.
>
> Now I am totally baffled.
>

Which indicates there is some problem with your original code.  It could 
be anything - including misplaced /*...*/ comments, for instance.

But I looked again at your code, and I'm confused,  In class A you have

public function b().

And in class B you have

public function a().

Which is it?

Also, you are aware, aren't you, that this follows the old style PHP 
constructors (which are still valid) where the constructor's name is the 
name of the class (instead of __construct() ).

-- 
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex@attglobal.net
==================

[toc] | [prev] | [next] | [standalone]


#2185

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2011-06-15 14:21 +0200
Message-ID<1532095.qVoOGUtdWV@PointedEars.de>
In reply to#2168
sheldonlg wrote:

> On 6/14/2011 8:45 PM, Jerry Stuckle wrote:
>> Id you created it properly, then the constructor in B should be calling
>> b::y().
>>
>> I still suggest you have a mistake in your code.
> 
> No, both constructors are there but are empty.
> 
> […] I […] copied the entire files into a test area […].  I then eliminated
> all methods that were not called, eliminated all includes that were no
> longer needed in the classes, and modified the important routines to only
> do the printing and the one calling routine in the class to only call the
> prescribed method […].  So, besides the constructors (which were empty)
> the base class had two methods and the overload class had one (with the
> name as the final method invoked in the base class).  The only typing I
> did was putting print statements in the final invoked methods to identify
> which one was doing the output.
> 
> […] what happened was that the output was from the overloaded method, not
> the base method. […]

   Talk is cheap. Show me the code.
     -- Linus Torvalds (2000-08-25)

<http://www.catb.org/~esr/faqs/smart-questions.html#beprecise> ff.


PointedEars
-- 
    realism:    HTML 4.01 Strict
    evangelism: XHTML 1.0 Strict
    madness:    XHTML 1.1 as application/xhtml+xml
                                                    -- Bjoern Hoehrmann

[toc] | [prev] | [next] | [standalone]


#2198

Fromsheldonlg <sheldonlg@thevillages.net>
Date2011-06-15 12:55 -0400
Message-ID<itao5l$nof$1@dont-email.me>
In reply to#2168
Problem solved!  It was a case of a little stupidity on my part.  I put 
the new overloaded method into the wrong overloading class.  Ergo, it 
was never reached when I ran the application because it wasn't there. 
In the example, it went to the right place and printed as coming from 
the overloaded method.  Sometimes........

Anyway, when I put it in the proper file, it functioned exactly as I had 
originally anticipated (and meant to program).

Thanks to all who devoted time and made suggestions.  I am sorry to have 
wasted your time.

-- 
Shelly

[toc] | [prev] | [next] | [standalone]


#2195

FromMichael Fesser <netizen@gmx.de>
Date2011-06-15 18:04 +0200
Message-ID<cblhv6d7hpa1gf7p5curfarqegijv098hv@mfesser.de>
In reply to#2165
.oO(Jerry Stuckle)

>Unfortunately, PHP doesn't really implement OO constructs very well - in 
>fact they to a pretty piss poor job of it.  One of the problems is with 
>virtual functions, as you found.  A good OO language would work like you 
>want, but PHP doesn't - the constructor for A will, in this case, only 
>call a function in A.

What do you mean?

<?php
class A {
  public function __construct() {
    $this->y();
  }

  public function y() {
    print __METHOD__."\n";
  }
}

class B extends A {
  public function y() {
    print __METHOD__."\n";
  }
}

$a = new A();
$b = new B();
?>

$ php -f constructor.php
A::y
B::y

Pretty much what I expect.

>In C++, Smalltalk, Java and most other OO 
>languages, you could define y() as virtual and the constructor for A 
>would call the function y() in B.

In PHP non-private methods are always virtual and in the above example
the constructor in A calls the method in B.

Micha

[toc] | [prev] | [next] | [standalone]


#2197

FromJerry Stuckle <jstucklex@attglobal.net>
Date2011-06-15 12:53 -0400
Message-ID<itao2v$mhc$1@dont-email.me>
In reply to#2195
On 6/15/2011 12:04 PM, Michael Fesser wrote:
> .oO(Jerry Stuckle)
>
>> Unfortunately, PHP doesn't really implement OO constructs very well - in
>> fact they to a pretty piss poor job of it.  One of the problems is with
>> virtual functions, as you found.  A good OO language would work like you
>> want, but PHP doesn't - the constructor for A will, in this case, only
>> call a function in A.
>
> What do you mean?
>
> <?php
> class A {
>    public function __construct() {
>      $this->y();
>    }
>
>    public function y() {
>      print __METHOD__."\n";
>    }
> }
>
> class B extends A {
>    public function y() {
>      print __METHOD__."\n";
>    }
> }
>
> $a = new A();
> $b = new B();
> ?>
>
> $ php -f constructor.php
> A::y
> B::y
>
> Pretty much what I expect.
>
>> In C++, Smalltalk, Java and most other OO
>> languages, you could define y() as virtual and the constructor for A
>> would call the function y() in B.
>
> In PHP non-private methods are always virtual and in the above example
> the constructor in A calls the method in B.
>
> Micha

Ah, you're right, Micha.  This was finally fixed.  It didn't used to 
work that way :)

-- 
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex@attglobal.net
==================

[toc] | [prev] | [next] | [standalone]


#2171

FromDenis McMahon <denis.m.f.mcmahon@gmail.com>
Date2011-06-15 03:41 +0000
Message-ID<4df829d0$0$32280$bed64819@gradwell.net>
In reply to#2162
On Tue, 14 Jun 2011 18:27:20 -0400, sheldonlg wrote:

>> This code:
>>
>> <?php
>>
>> abstract class A {
>>
>>       public function x() {
>>           print "x() In class A\n";
>>           $this->y();
>>       }
>>
>>       public function y() {
>>           print "y() In class A\n";
>>       }
>>
>>       public function a() {
>>           print "a() In class A\n";
>>       }
>>
>> }
>>
>> class B extends A {
>>
>>       public function y() {
>>           print "y() In class B\n";
>>       }
>>
>> }
>>
>> print "instantiate\n";
>>
>> $x = new B();
>>
>> print "call function\n";
>>
>> $x->x();
>>
>> ?>
>>
>> gives:
>>
>> instantiate
>> a() In class A
>> call function
>> x() In class A
>> y() In class B
>>
>> Not sure, though, if that solves your problem or not?

> Why did your example print out that last line.  It was never called.
> Why did it use it as a constructor?  That doesn't seem to make sense.

OK, the calls as I understand it in my code.

First I print "instantiate"

Next, "$x = new B();" causes $x to be created, which instantiates b, 
which extends a, which causes A::a() to be called as a constructor 
function, which prints "a() In class A".

Then I print "call function"

Finally, "$x->x();" calls A::x() which prints the line "x() In class A" 
and then calls $this->y() which finds B::y() which prints the line "y() 
In class B".

I'm not sure if your complaint is about the sequence of call of the 
constructor functions during instantiation of $x, or the call chain after 
instantiation, which is why I gave the functions called after 
instantiation different names (x and y) to the constructor function in 
class A.

I believe that in your code, A::a() was being called as a constructor at 
instantiation, and A::b() was calling B::a() after instantiation. That's 
certainly suggested by:

<?php

abstract class A {
     public function a() {
         print "a() In class A\n";
     }
     public function b() {
         print "b() In class A\n";
         print "b() In class A calling \$this->a()\n";
         $this->a();
         print "b() In class A returned from \$this->a()\n";
     }
}

class B extends A {
     public function a() {
         print "a() In class B\n";
     }
}

print "instantiate\n";
$x = new B();
print "call function\n";
$x->b();
?>

giving:

instantiate
a() In class A
call function
b() In class A
b() In class A calling $this->a()
a() In class B
b() In class A returned from $this->a()

Note that A::a() is called as constructor during instantiation of $x
A::b() calling $this->a() after instantiation of $x calls B::a() and not 
A::a().

Your initial complaint was about A::a() being called, is it possible that 
the A::a() call that you observed was from instantiation and not the call 
to $x->b()?

Rgds

Denis McMahon

[toc] | [prev] | [next] | [standalone]


#2193

FromMichael Fesser <netizen@gmx.de>
Date2011-06-15 18:02 +0200
Message-ID<3ilhv6hokjelo95b31fajeqdcpnd6ae1nk@mfesser.de>
In reply to#2162
.oO(sheldonlg)

>On 6/14/2011 2:32 PM, Denis McMahon wrote:
>
>> This code:
>>
>> <?php
>>
>> abstract class A {
>>
>>       public function x() {
>>           print "x() In class A\n";
>>           $this->y();
>>       }
>>
>>       public function y() {
>>           print "y() In class A\n";
>>       }
>>
>>       public function a() {
>>           print "a() In class A\n";
>>       }
>>
>> }
>>
>> class B extends A {
>>
>>       public function y() {
>>           print "y() In class B\n";
>>       }
>>
>> }
>>
>> print "instantiate\n";
>>
>> $x = new B();
>>
>> print "call function\n";
>>
>> $x->x();
>>
>> ?>
>>
>> gives:
>>
>> instantiate
>> a() In class A
>> call function
>> x() In class A
>> y() In class B
>>
>> Not sure, though, if that solves your problem or not?
>>
>> Rgds
>>
>> Denis McMahon
>
>I modified B to give it an explicit constructor.  It still didn't work. 
>  Why did your example print out that last line.  It was never called. 

The command $x->x() would call B::x(), but there's no such method. So
the inherited method A::x() is called, which then calls $this->y(). And
since $this refers to an instance of class B, B::y() is called, leading
to the last line of output.

Micha

[toc] | [prev] | [next] | [standalone]


#2184

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2011-06-15 14:01 +0200
Message-ID<2975511.SPkdTlGXAF@PointedEars.de>
In reply to#2150
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

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.php


csiph-web