У меня нет большого опыта работы со статически типизированными языками (в настоящее время изучаю Scala и любя его!), но я заметил, что они никогда не имеют ничего похожего на Ruby method_missing или ColdFusion onMissingMethod. Есть ли какое-то присущее ограничение в статически типизированных языках, которые мешают или затрудняют это?
Что препятствует тому, чтобы статически типизированный язык имел что-то вроде Ruby method_missing?
Ответ 1
Конечно, может быть добавлен механизм их обработки, но он не согласуется с тем, что статическая типизация: определение времени компиляции в вашей программе не содержит ошибок типа.
Добавление
Scala 2.9 введен экспериментальный вариант, позволяющий эту динамическую обработку доступа к типам таким образом, чтобы в противном случае была бы невозможна проверка статического типа. Он был усовершенствован и не был экспериментальным в 2.10, хотя он по-прежнему контролируется флагом функции по умолчанию. Вы можете прочитать об этом в документе SIP 17. См. SIP 18 для объяснения Scala 2.10 "модуляции" и флагов функций.
Ответ 2
Scala версия 2.9 вводит эту функциональность с помощью признака Dynamic
(scaladoc). Классы, которые расширяют Dynamic
, получают магический метод applyDynamic(methodName, args)
, который аналогичен Ruby method_missing
. Начиная с Scala 2.9, параметр -Xexperimental
должен быть включен для использования Dynamic
.
Ответ 3
В статически типизированных языках функции-члены вызываются напрямую. Если компилятор не может определить, какую функцию-член вызывать, программа не будет компилироваться. Вызов метода в этом смысле статичен.
В динамически типизированных языках функции-члены не вызываются напрямую. Скорее, вызывающий код отправляет сообщение объекту, а затем среда выполнения языка определяет, что делать с этим сообщением. Например, среда выполнения сканирует объект для метода с тем же именем и затем сканирует объект для метода с именем method_missing
. Вызов метода в этом смысле является динамическим.
С# 4 сочетает статическую типизацию с динамической типизацией. Переменная может иметь тип времени компиляции dynamic
. Любые вызовы методов для этой переменной будут обрабатываться так же, как и в динамически типизированных языках. Любые вызовы методов для переменных со статическими типами будут обрабатываться как в статически типизированных языках.
# static invocation, bound at compile time by the compiler
var s = 6;
s.ToString();
# dynamic invocation, handled at runtime by the CLR
dynamic d = 6;
d.ToString();
Ответ 4
Просто для дальнейшего сообщения Рэндалла это возможно, но причина, по которой он идет против статической парадигмы, заключается в том, что она выходит за рамки "динамической отправки". Динамическая отправка с радостью позволяет вам отправить функцию, динамически связанную с известной статической частью кода. то есть компилятор устанавливает отправку, которая детерминированно выполняется во время выполнения, с ее точки зрения.
Что делает вызов method_missing
, по сути делает "catch all", где вы решаете, что делать на основе имени метода, используя оператор switch или что-то эквивалентное (что, я уверен, вы знаете). Таким образом, компилятор понятия не имеет, что произойдет здесь. Скажем, компилятор сделал что-то вроде:
if (function is known at compile time)
{
provide static call or dynamic call to "some" derivation
}
else
{
bind the function call to obj.method_missing(...) and pass in the "details"
}
Затем вы должны указать method_missing
следующим образом:
def method_missing(intendedFunctionName, arguments)
{
if (intendedFunctionName is "X")
{
X may not need arguments, so just do something
}
else if (intendedFunctionName is "Y")
{
Y expects 5 arguments of varying types
Throw exception if there isn't the right number or types
}
... etc ...
}
Попросив компилятор отправить вам произвольные (т.е. неизвестные во время компиляции) аргументы произвольных типов с intendedFunctionName
, которые вы, возможно, не учитываете... ну, это не очень безопасно, и Scala - это статически безопасный язык.
Да, это выполнимо, но не в духе статического языка. Если вам действительно нужен такой тип гибкости, программирование полиглота, вероятно, ваш друг.
Примечание. Objective-C не является строго статически типизированным. Существует механизм выполнения, на котором выполняется код, и система динамического набора не позволяет удалять или вставлять код как C/С++.
Ответ 5
Objective-C имеет "method_missing" (в частности, forwardInvocation и methodSignatureForSelector) и, возможно, статически типизирован. Это работает потому, что будет обрабатывать ошибки статического типа как предупреждения, а не ошибки во время компиляции, поскольку отправка метода происходит во время выполнения в гораздо большей степени, чем что-то вроде виртуальных методов на С++ (и именно поэтому вы можете иметь "method_missing" ).