Consider this condensed case from real code:
class A { protected int x; void init (int i) {x = i;} int get() {return x;} }
class B { protected int x; void init (string s) {x = (int) s;} int get() {return x;} }
A create_a() { B b = B(); b->init ("17"); return [object(A)] b; }
In create_a() I try to cheat and return a B as if it were an A, by using a type cast. It doesn't work:
/home/mast/foo.pike:19:Soft cast of { B = object(implements /home/mast/foo()->B) } to { A = object(implements /home/mast/foo()->A) } isn't a valid cast.
(Side note: This error message doesn't explain why the cast is invalid. Presumably it's due to the prototype of init(), but unlike other type errors it doesn't go into detail.)
Let's assume that in this case I know that the type difference of the init() prototype isn't relevant (e.g. it's a function only used in the object factory and therefore never called outside create_a).
Shouldn't it be possible to use type casts to make the compiler shut up? I can do this workaround:
A create_a() { B b = B(); b->init ("17"); object b2 = b; return [object(A)] b2; }
But avoiding that phony extra variable isn't possible; this variant is still nailed:
A create_a() { B b = B(); b->init ("17"); return [object(A)] [object] b; }
if i understand correctly, init needs to be public so that create_a() can call it, but it is not required to be part of A api otherwise.
wouldn't in that case making it optional help?
greetings, martin.
if i understand correctly, init needs to be public so that create_a() can call it, but it is not required to be part of A api otherwise.
Correct. If pike had a feature like C++ "friend" then it wouldn't have to be public.
wouldn't in that case making it optional help?
No, optional only helps if the identifier is missing from either class, not if there's a type conflict. I think that is as it should be.
For these kind of things a 'friend' declaration coupled with private would also work, if we could combine it with objects of type A being allowed to access private methods in other objects of type A it would be a plus. :-)
class A { friend A create_a(); // types here not really needed in pike, though. protected int x; protected void init (int i) {x = i;} int get() {return x;} }
class B { friend A create_a(); // types here not really needed in pike, though. protected int x; protected void init (string s) {x = (int) s;} int get() {return x;} }
A create_a() { B b = B(); b->init ("17"); return b; // And all is well, since the types match. }
i previously thought that friend in pike makes no sense because it is used to hide things from the public api. but that would not work in pike because anyone could write a class that looks like A and then access the hidden symbol anyways.
how ever in this case the goal is to hide it from the typechecker...
greetings, martin.
There is a difference between 'looks like' and 'is', though. I would have to assume that 'is' is what will be used to bypass 'private'.
pike-devel@lists.lysator.liu.se