Hi there,
the example code from docs.elementcompiler.com regarding “Private Interface Members” in Qxygene does not seem to work.
(E425) Element is not allowed in an interface type
Hi there,
the example code from docs.elementcompiler.com regarding “Private Interface Members” in Qxygene does not seem to work.
(E425) Element is not allowed in an interface type
My apologies for this. i’ll need to see whether the docs are wrong or the compiler; for now, visibility sections don’t work, but visibility modifiers after the methid do:
type
ILogger = public soft interface
method Log(aInfo: String);
method Log(aFormat: String; params aParameters: array of Object);
begin
Log(CustomFormat(aFormat, aParameters));
end;
method CustomFormat(aFormat: String; params aParameters: array of Object): String; private;
begin
//...
end;
end;
Logged as bugs://E25782.
Sorry to say this - if i add visibility modifiers as recommended, it compiles but still doesn’t work.
“Foo” in this testcase is private, but appears in CC and is callable.
namespace ConsoleApplication1;
type
ITest = public interface
method Foo; private;
method Bar;
end;
TestObject = public class(ITest)
private
method Foo;
begin
writeLn('Hmm...');
end;
public
method Bar;
begin
writeLn('Hello');
end;
end;
Program = class
public
class method Main(args: array of String): Int32;
begin
var o: ITest := new TestObject;
o.
readLn;
end;
end;
end.
Separate bug; logging.
Logged as bugs://E25783.
Note that the fix for this will be that it doesn’t compile. It doesn’t really make sense to have an interface method (that another class is required to implement) that’s private. How would you implement it ?
I only tried to use a feature that is is described in the documentation.
But indeed - interfaces with private members MAY be useless. I struggeled over this, because i tried to hide some wired compiler-generated stuff around property getters. Maybe there is another problem there and i tried to fix the problem from the wrong end.
(There seems to be an issue with interface property getters and setters and some auto-generated extension class with mappings in it. But I can’t understand that exactly at the moment and still have to play with it first.)
Btw: code completion inserts a private method (section! AND method-wise) if you let it generate an getter method…
ITest = public interface
private
method GetSomeProp: Integer; private;
begin
end;
property SomeProp: Integer read GetSomeProp
end;
the idea of the feature was originally to hide the methods that do have an implementation (to be called from other methods in the same interface). Obviously it shouldn’t do that for “real” interface methods. We’ll fix the methods. (Also the CC completion is wrong)
I think, i found the reason, which caused me to fiddle around with this “private-interface-stuff”:
Delegating the Implementation of an Entire Interface reveals hidden compiler generated methods and makes them accessible for the caller.
namespace ConsoleApplication42;
type
ITest = public interface
property Foo: Integer read;
end;
TestImplementer = public class(ITest)
public
property Foo: Integer read 42;
end;
TestOMat = public class(ITest)
private
fTest := new TestImplementer; implements public ITest;
public
end;
Program = class
public
class method Main(args: array of String): Int32;
begin
var tom := new TestOMat;
writeLn(tom.get_Foo); // <-- Visible to cc and callable here. Shouldn't be there.
var ti := new TestImplementer;
writeLn(ti.get_Foo); // <--. Invisble to cc but nevertheless callable here.
readLn;
end;
end;
end.
One can say, it is an cosmetic issue, but i have an interface with a handful of properties and have wondered where all the “get_”-methods came from.
Logged as bugs://E25786.
Can you tell me why you added the public in there?
fTest := new TestImplementer; implements public ITest;
Without public it would be private; but I would like to know why you did it this way.
bugs://E25786 was closed as no change required.
If I omit the “public” then the implemented interface is not accessible from the outside without a cast. Not even if I move the implementing object to the “public” area.
(Which I didn’t want, because the “implementer” shouldn’t necessarily be directly visible.)
But since “TestOMat” is defined to implement ITest, it should work without cast, IMO.
namespace ConsoleApplication42;
type
ITest = public interface
property Foo: Integer read;
end;
TestImplementer = public class(ITest)
public
property Foo: Integer read 42;
end;
TestOMat = public class(ITest)
private
public
fTest := new TestImplementer; implements ITest;
end;
Program = class
public
class method Main(args: array of String): Int32;
begin
var tom := new TestOMat;
writeLn(tom.Foo); // <-- (E44) No member "Foo" on type "TestOMat"
readLn;
end;
end;
end.
Yeah that’s what I was going for. public will do exactly what you want. I do think get_* probably shouldn’t be visible (but it should be callable).
bugs://E25782 was closed as fixed.
bugs://E25783 was closed as fixed.
Yes. with “public:” the interface members become public on the class type; without, they are only available via cast to the interface. That’s the entire point of using “public” there — IOW this seems to be working exactly as it should.