Hi all,

On Sun, Feb 15, 2015 at 7:53 AM, Yasuo Ohgaki <yohg...@ohgaki.net> wrote:

> On Sat, Feb 14, 2015 at 8:06 PM, Robert Stoll <p...@tutteli.ch> wrote:
>
>> The theory is actually quite simple. Roughly it says that if you use a
>> type hint of a certain class then you can rely on all pre/post-conditions
>> of this class even if a sub-class is passed. Hence the sub-class cannot
>> have more restrict conditions. Consider the following (no longer sure which
>> syntax is the one you intend to use, so I just use pre and post):
>>
>> class A{
>>   function foo($x){
>>      pre($x > 100);
>>   }
>> }
>>
>> class B extends A{
>>   function foo($x){
>>     pre($x > 50); // less restrictive, that's fine
>>   }
>> }
>>
>> class C{
>>   function foo($x){
>>     pre($x > 150); //more restrictive that's not allowed
>>   }
>> }
>>
>> function foo(A $a){
>>   $a->foo(101); // that is ok as long as LSP is not violated
>> }
>>
>> foo(new A()); //that's fine
>> foo(new B()); //fine as well
>> foo(new C()); //nope, C violates LSP and thus will result in an error
>>
>
> Correct. D does not allow to change parents contract. D does fancy check
> for "overridden" methods
> so that child cannot change parent behavior. I agree this is correct for
> type safety.
>
> Since D is strongly typed, D has "overloading" and D user can get around
> with the previous restriction
> easily.
> e.g. foo(x, y) in class B will ignore A::foo contract at all. Same applies
> to type difference, since
> this is what "overloading" is.
>
> PHP is weakly typed. There is no point follow D principle for "overridden"
> methods because PHP type
> is weak and PHP does not have "overloading".
>
> I think this answers to your question.
>
> Regards,
>
> P.S. Are we really going to consider strict type safety for PHP??
>

I wrote simple D program "sample.d" to play with. Install D, then

dmd sample.d && ./sample

====sample.d====
import std.stdio;

class A {
int x = 1;
int y = 2;

 public:
void set (int x, int y)
in {
assert(x > 0);
assert(y > 0);
}
body {
this.x = x;
this.y = y;
}
 int mul()
out (ret) {
assert(ret > 0);
}
body {
return x * y;
}

invariant {
assert(this.x > 0);
assert(this.y > 0);
}
}

class B : A {
int a;
int b;
 override void set (int a, int b)
in {
assert(a > 4);
assert(b > 2);
}
body {
this.a = a;
this.b = b;
}
 override int mul()
out (ret) {
assert(ret > 4);
}
body {
return a * b;
}

invariant {
assert(this.x > 0);
assert(this.y > 0);
}
}

class C : A {
override void set (int x, int y)
in {
// Cannot work with override
assert(x > -4);
assert(y > -2);
}
body {
this.x = x;
this.y = y;
}
 override int mul()
out (ret) {
assert(ret > -4);
}
body {
return x * y;
}

// This cannot work. Less restrictive than parent
invariant {
assert(this.x > -4);
assert(this.y > -2);
}
}


void main()
{
A a = new A;
B b = new B;
C c = new C;
a.set(4,2);
writeln("Ans: ", a.mul());
// -1 is invalid
//a.set(-1, 0); core.exception.AssertError@sample.d(10): Assertion failure

b.set(5,3); // Fine with B. B is different type.
writeln("Ans: ", b.mul());
}
=================


As you can see, D has type safety by contracts and does non-intuitive
checks.
Question is "Does PHP need this kind of type safety?"

I totally agree strict type safety is good for writing correct programs,
BTW.
D has type safety feature since it has strong type. If PHP is going to be
strongly typed language as scalar type hint RFC, and might be stronger
type than now. We may consider stricter types later. It's not just time for
it. IMHO.
PHP may be extended to check contracts like D when
declare('strict_types'=1).

Regards,

--
Yasuo Ohgaki
yohg...@ohgaki.net

Reply via email to