Open RblSb opened 2 months ago
What's wrong with that? Getter and setter are implementation details compatible with the contract as long as Void->Int is a subtype of Void->Float, covariance stuff and all...
class Test {
static function main() {
var myFunc:Void->Float = foo;
}
static function foo():Int {
return 0;
}
}
Main is also a subtype of IObj with its own width:Int, as long as read-only access is covariant on the return type.
Yes, i think implementing Float as Int should be allowed, this is pretty handy for subclasses to restrict Float a little. But it doesn't work in all cases, only for (default, ...)
, but not for get, set
or simple fields:
interface IMain {
var a(default, never):Float;
var b(default, null):Float;
var c:Float;
var d(get, set):Float;
}
class Main implements IMain {
public var a:Int = 0; // fine, good
public var b:Int = 0; // fine, good
public var c:Int = 0; // Field c has different type than in IMain
public var d(get, set):Int; // Field d has different type than in IMain
function get_d():Int
return 0;
function set_d(d:Float):Int
return 0;
static function main() {
final main = new Main();
// Allowed because there is no `a(default, never)` in Main, bad
main.a = 1;
}
public function new() {}
}
And there is another bug, you can have more restricted type in interface with (default, never)
, but compiler will not inference (default, never)
to your implementation.
It should work for read access only. In case of write access relation is also a contravariant so subtyping is impossible.
public var d(get, set):Int
should accept Float
for writing by contract so compilation error is correct for this case.
The same for second case: interface may and should be more restricted than implementation but not vice versa.