FUDforum
Fast Uncompromising Discussions. FUDforum will get your users talking.

Home » Imported messages » comp.lang.php » An overloading question
Show: Today's Messages :: Polls :: Message Navigator
Switch to threaded view of this topic Create a new topic Submit Reply
An overloading question [message #174480] Tue, 14 June 2011 16:49 Go to next message
sheldonlg is currently offline  sheldonlg
Messages: 166
Registered: September 2010
Karma: 0
Senior Member
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
Re: An overloading question [message #174483 is a reply to message #174480] Tue, 14 June 2011 18:32 Go to previous messageGo to next message
Denis McMahon is currently offline  Denis McMahon
Messages: 634
Registered: September 2010
Karma: 0
Senior Member
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
Re: An overloading question [message #174492 is a reply to message #174483] Tue, 14 June 2011 22:27 Go to previous messageGo to next message
sheldonlg is currently offline  sheldonlg
Messages: 166
Registered: September 2010
Karma: 0
Senior Member
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
Re: An overloading question [message #174495 is a reply to message #174492] Tue, 14 June 2011 23:12 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
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(at)attglobal(dot)net
==================
Re: An overloading question [message #174496 is a reply to message #174495] Tue, 14 June 2011 23:43 Go to previous messageGo to next message
sheldonlg is currently offline  sheldonlg
Messages: 166
Registered: September 2010
Karma: 0
Senior Member
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
Re: An overloading question [message #174497 is a reply to message #174496] Wed, 15 June 2011 00:45 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
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(at)attglobal(dot)net
==================
Re: An overloading question [message #174498 is a reply to message #174497] Wed, 15 June 2011 01:58 Go to previous messageGo to next message
sheldonlg is currently offline  sheldonlg
Messages: 166
Registered: September 2010
Karma: 0
Senior Member
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
Re: An overloading question [message #174499 is a reply to message #174498] Wed, 15 June 2011 02:08 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
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(at)attglobal(dot)net
==================
Re: An overloading question [message #174501 is a reply to message #174492] Wed, 15 June 2011 03:41 Go to previous messageGo to next message
Denis McMahon is currently offline  Denis McMahon
Messages: 634
Registered: September 2010
Karma: 0
Senior Member
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
Re: An overloading question [message #174514 is a reply to message #174480] Wed, 15 June 2011 12:01 Go to previous messageGo to next message
Thomas 'PointedEars'  is currently offline  Thomas 'PointedEars'
Messages: 701
Registered: October 2010
Karma: 0
Senior Member
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
Re: An overloading question [message #174515 is a reply to message #174498] Wed, 15 June 2011 12:21 Go to previous messageGo to next message
Thomas 'PointedEars'  is currently offline  Thomas 'PointedEars'
Messages: 701
Registered: October 2010
Karma: 0
Senior Member
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
Re: An overloading question [message #174523 is a reply to message #174492] Wed, 15 June 2011 16:02 Go to previous messageGo to next message
Michael Fesser is currently offline  Michael Fesser
Messages: 215
Registered: September 2010
Karma: 0
Senior Member
.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
Re: An overloading question [message #174525 is a reply to message #174495] Wed, 15 June 2011 16:04 Go to previous messageGo to next message
Michael Fesser is currently offline  Michael Fesser
Messages: 215
Registered: September 2010
Karma: 0
Senior Member
.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
Re: An overloading question [message #174527 is a reply to message #174525] Wed, 15 June 2011 16:53 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
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(at)attglobal(dot)net
==================
Re: An overloading question [message #174528 is a reply to message #174498] Wed, 15 June 2011 16:55 Go to previous message
sheldonlg is currently offline  sheldonlg
Messages: 166
Registered: September 2010
Karma: 0
Senior Member
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
  Switch to threaded view of this topic Create a new topic Submit Reply
Previous Topic: check user log and redirect
Next Topic: use GET in include
Goto Forum:
  

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ]

Current Time: Sun Nov 10 16:49:32 GMT 2024

Total time taken to generate the page: 0.02658 seconds