Since more feedback may help here i also send this to php-dev

At 15:47 08.12.2002, Stanislav Malyshev wrote:
MB>> Therefor i would vote for allowing only decreasing the visibility or force
MB>> to keep it.

Decreasing visibility contradicts the basic inheritance principle - that
derived class "is-a" base class, i.e., basically, it can be used in any
place the base class is used. If you restrict methods in derived class, it
may lead to a situation where $foo->method() works with base class, but
fails with derived class - which is, as I said, against the inheritance
principle.
As for increasing visibility - I don't see major problem in it. What could
be the problem if derived class is allowed to open protected method to
public? After all, it could proxy it anyways...
Let me say two things first:
1) Visibility is about information hiding not showing.
2) You are wrong about 'is-a' in general. Our main problem here is that we
do not have a typecast operator.

1) Visibility modifiers are for information hiding. That is you can hide certain
implementation details. Each class has three interfaces: i) the interface
accessible from any other scope. ii) the interface accessible from any
derived class

Suppose you are going to design an encryption framework. Then you surely will
first design an interface. In php you will create an abstract class to accomplish
this. Then you will implement general features which will handle unencrypted
content and such. Also you may implement general key handling. In the class
hierarchy you will make all acess to uncencrypted content protected or even
private starting from here. Doing this you ensure that no user and in case of
private even no derived class can access unencrypted content.
=> Only information hiding = decreasing visibility.

Or suppose you have a class for content handling and you will base encryption on
top of this. Then you will derive the encryption handling from content handling and
mark unencrypted acess methods/properties as private.
=> Only information hiding = decreasing visibility.

Note the different motivations for deriving classes above.

More examples could be made but that's not the point here. The point is that
there is a need for decreasing visibility. And personally i do not see any need
for increasing visibility besides the 'is_a' comment.

When increasing the visibility you show functionality being hidden in a base class.
Most often this is done to fix wrong class design or to missuse baseclasses in ways
they are not designed for.

2) For our current implementation you are partly right with your comment on
'is_a' because you cannot use a parent interface of a class. But your comment
does not hold since 'is_a' does not work even without visibility in php like you want
it.

Example without visibility:

class A {
function println($msg) {
echo "$msg\n";
}
}
class B {
function println() {
// whatever...
}
}

when in this example you work on B instances with A's protocol you will see
that B's println does not recognize $msg. => When deriving classes in a typed
language an overloaded method must accept the same input and must return
the same output.

Maybe we decide that for PHP this is not a problem since we simply ignore
this fact what is possible in a loosely typed language. Otherwise deriving checks
would become much more complex since we need to store the input and check
for that, too. At least we must count required, optional and "..." input parameters
then.

In the above example I assumed we had inheritance working as in typed OO
languages. I further assumed that when having B as a subclass of A and b
as instance of B, b can be used with protocol A by using a typecast. That is:
is_a(b, A) === true implies that even methods made private in B can be used
with protocol A if they are public there. It does not imply that you can use A's
protocol without typecasting b to A. When in this scenario all methods are linked
dynamically we have what we want: by calling a method from b typecysted to A
the overwritten method from class B is being invoked.

Immediate conclusion: I tried changing visibility in other languages and read again
about it in some books. I came to the conclusion that both increasing and
decreasing works in some languages but only found hints for the need of
information hiding (decreasing visibility).

Example:
#include <iostream>

class A {
public:
virtual void pub() { cout << "A::pub" << endl; };

protected:
virtual void pro() { cout << "A::pro" << endl; };
};

class B: public A {
protected:
virtual void pub() { cout << "B::pub" << endl; }; // You can also make this private

public:
virtual void pro() { cout << "B::pro" << endl; };

};

int main(int argc, char **argv) {
B *b = new B();
b->pro();
dynamic_cast<A*>(b)->pub();
// b->pub(); B::pub is protected
delete b;
}

In this C++ example dynamic_cast is used for "is_a". When dynamic_cast<X*>(p)
returns NULL the variable p is not of type X or one of it's parent.

Problem: Increasing the visibility is a bit strange (at least for me) but current php
design can only handle increasing or keeping visibility. Further more current
implemetation of 'is_a' does not work when decreasing visibility is allowed.

Solution: Force keeping visibility or or allow increasing as of now.

Next step: We can handle decreasing visibility by modifying zendengine.
When calling a method we must look into the calling scope and see what
visibility a function has for the situation a method is called dynamically from
a classes scope or the scope of one of its parents. This requires walking on
the class hierarchy what is slow but i do not see a solution to avoid it and
handling privates correctly.

Next Next Step: typecast

I think the engine can be expanded by a typecast function or operator: Say "cast".
For eaxample "cast($obj,$class)" will result in an error if $class is not a parent of
$obj's class or equals $obj's class itself. When it is successfull we would simply
set the the visibility to the visibility of the method in that scope. When $class does
not have the method being called then it is even an error if $obj's class has. This
is affected by the way privates work and affetcs that also (inheriting privates or not).

As a sideeffect we could handle decreasing the visibility without a need for walks
on the inheritance tree.

Problem left: Input/Output checking. As php is a loosely typed language i suppose
we are not going to verify that derived classes overload methods correctly. Said this
we perhaps even make the input protocol of abstract methods optional (no need for
the brackets).

Sorry for the late answer :-)

regards
marcus


--
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to