#dart
#dart
Вопрос:
Function foo = (int x) =&&t; x;
if (foo is Function(Object)) {
print('Bar'); // Doesn't print
}
По моему мнению, Function(int)
это подтип Function(Object)
, поскольку type int
является подтипом type Object
и, следовательно, if
условие должно возвращать true
, но это не так. Почему это так?
Я не получил никакого хорошего названия для этого вопроса, не стесняйтесь изменить его.
Ответ №1:
Это не так.
Суть подтипов в том, что экземпляр подтипа может использоваться везде, где ожидается экземпляр супертипа (также известный как «взаимозаменяемость»).
Function(Object)
Может быть вызвана с любым объектом в качестве аргумента. Она может вызываться как с "foo"
, так и 42
в качестве аргументов. Function(int)
Не может быть вызвана со строкой в качестве аргумента. Это означает, что a Function(int)
не может быть заменено там, где ожидается a Function(Object)
, и система типов действительно не создает Function(int)
подтипа Function(Object)
.
Вместо этого она создает Function(Object)
подтип Function(int)
, потому что если функция, которая может быть вызвана с любым аргументом, то ее можно использовать везде, где требуется функция, принимающая int
аргумент — потому что она принимает int
.
В общем случае, R1 Function(P1)
тип функции является подтипом R2 Function(P2)
, если R1
является подтипом R2
и P2
является подтипом P1
. Обратите внимание на обратный порядок типов параметров. Типы параметров ковариантны.
Подумайте об этом так: функцию можно использовать там, где ей присвоен аргумент типа P и ожидается, что она вернет значение типа R, если (и только если) она принимает любой P аргумент и, возможно, больше, и все значения, которые она может возвращать, должны быть R значениями , но не обязательно всеми R значениями.
То есть тип функции является подтипом, R Function(P)
если он принимает минимум P
и возвращает максимум R
.
Комментарии:
1. Я уверен, что нигде в Интернете не найду лучшего объяснения, чем это. Большое спасибо, Лассе, сэр.
Ответ №2:
Хотя это не сразу интуитивно понятно, подтипирование противоположно: Function(Object)
является подтипом Function(int)
. Действительно, тип A
может быть подтипом B
только в том случае, B
если все, что имеет значение about A
, также имеет значение about,,,. Function(Object)
всегда может быть вызвана с int
аргументом, но Function(int)
не может быть вызвана с произвольным Object
, поэтому:
Function foo = (Object x) =&&t; x;
if (foo is Function(int)) {
print('Bar'); // prints!
}
Другими словами, функции контравариантны по типу параметра.
Комментарии:
1. Привет, спасибо за ваш ответ. Но
Function(int)
также может быть вызвана с помощьюObject
.2. @iLoveFlutterDocs, который вы не можете вызвать
Function(int)
, например, с помощью строки, не так ли?3. Я думаю, вы меня неправильно поняли. Скажем,
Object
являетсяint
ли онаObject obj = 1
, тогда вы можете вызватьFunction(int)
сobj
помощью.4. @iLoveFlutterDocs Ах, я понимаю, что ты имеешь в виду. Система типов Dart кажется немного более расслабленной, поэтому она опускает некоторые статические проверки для вызовов функций. Но это все еще применимо к
is
оператору. Нужно найти, действительно ли это где-то задокументировано.