blob: 4d29890e80bfa04b8a2d456c5a0dde5fecfa3706 [file] [log] [blame]
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
// Testing that `noSuchMethod` appears to use implicit forwarders (we don't
// care how it's actually implemented, but it should look like that).
import 'package:expect/expect.dart';
// "Template" class: Something to emulate.
class A {
int foo(String s) => s.length;
}
// Emulate `A`, but only dynamically.
class B {
noSuchMethod(_) => 31;
}
// Emulate `A`, including its type.
class C implements A {
noSuchMethod(_) => 41;
}
// Emulate `A` with its type, based on an inherited `noSuchMethod`.
class D extends B implements A {}
void test(A a, int expectedValue) {
// Regular superinterfaces can be supported by `noSuchMethod`.
Expect.equals(expectedValue, a.foo('Hello!')); //# 04: ok
// `noSuchMethod` triggers generation of forwarders, so a statically
// known instance method tear-off yields a `Function`, also when invoked
// dynamically.
Expect.isTrue(a.foo is Function); //# 05: ok
Expect.isTrue((a as dynamic).foo is Function); //# 06: ok
// For an unknown member name the invocation must be dynamic, and in that
// case it does not match a forwarder, but we invoke `noSuchMethod`.
Expect.equals(expectedValue, (a as dynamic).bar); //# 07: ok
}
main() {
// Dynamic invocations can make a `B` seem to implement `A`.
Expect.equals(31, (new B() as dynamic).foo('Hello!')); //# 01: ok
// But `noSuchMethod` does not affect the type or interface of a class.
A a; //# 02: continued
Expect.throws(() => a = new B() as dynamic); //# 02: ok
new B().foo('Hello!'); //# 03: compile-time error
test(new C(), 41);
test(new D(), 31);
}