Да, это действительно так. Вроде.
Newspeak не имеет статического состояния и глобального состояния. Это означает, что единственный возможный способ получить доступ к зависимости - это ввести ее явно. Очевидно, это означает, что язык или, в случае Newspeak, более точно, IDE должен облегчить внедрение зависимостей, в противном случае язык будет непригодным для использования.
Таким образом, язык не предназначен для DI, скорее необходимость в DI является следствием языкового дизайна.
Если нет статического состояния и нет глобального состояния, то вы не можете просто «достучаться» до эфира и что-то вытянуть. Например, в Java структура пакета является статическим состоянием. Я могу просто сказать, java.lang.String
и у меня есть сам String
класс. Это невозможно в Newspeak. Все, с чем вы работаете, должно быть явно предоставлено вам, иначе вы просто не сможете этого достичь. Итак, все является зависимостью, и каждая зависимость является явной.
Вы хотите строку? Ну, вы должны сначала попросить stdlib
объект передать вам String
класс. О, но как вы получаете доступ к stdlib
? Ну, вы должны сначала попросить platform
передать вам stdlib
объект. О, но как вы получаете доступ к platform
? Ну, вы должны сначала попросить кого-то еще передать вам platform
объект. О, но как вы можете получить доступ к этому кто-то, что есть? Что ж, вы должны сначала попросить еще кого-нибудь передать вам объект.
Как далеко это заходит в кроличью нору? Где останавливается рекурсия? Вообще-то, на самом деле. Это не останавливает. Тогда как вы можете написать программу в Newspeak? Ну, строго говоря, вы не можете!
Вам нужна какая-то внешняя сущность, которая связывает все это вместе. В Newspeak эта сущность является IDE. IDE видит всю программу. Это может связать разрозненные части вместе. Стандартный шаблон в Newspeak состоит в том, что в центральном классе вашего приложения есть platform
метод доступа , а IDE Newspeak внедряет в этот метод объект, который имеет методы, которые возвращают некоторые основные потребности программирования: String
класс, Number
класс, Array
класс, и так далее.
Если вы хотите протестировать свое приложение, вы можете внедрить platform
объект, File
метод которого возвращает класс с помощью фиктивных методов. Если вы хотите развернуть свое приложение в облаке, вы внедряете платформу, File
класс которой фактически поддерживается Amazon S3. Кроссплатформенные графические интерфейсы работают путем внедрения различных структур графического интерфейса для разных ОС. У Newspeak даже есть экспериментальный компилятор Newspeak-to-ECMAScript и среда графического интерфейса с HTML-поддержкой, которая позволяет переносить полнофункциональное приложение с графическим интерфейсом пользователя с собственного рабочего стола в браузер без изменений, просто добавляя различные элементы графического интерфейса.
Если вы хотите развернуть свое приложение, IDE может сериализовать приложение в объект на диске. (В отличие от своего предшественника, Smalltalk, Newspeak имеет формат сериализации объектов вне изображения. Вам не нужно брать с собой все изображение именно потому, что все зависимости внедрены: IDE точно знает , какие части системы ваше приложение использует, а что нет. Таким образом, он сериализует в точности подключенный подграф объектного пространства, составляющего ваше приложение, и ничего более.)
Все это работает просто, доводя объектную ориентацию до крайности: все является вызовом виртуального метода («отправка сообщения» в терминологии Smalltalk, потомком которого является Newspeak). Даже поиск суперкласса - это вызов виртуального метода! Возьми что-то вроде
class Foo extends Bar // using Java syntax for familiarity
или в Newspeak:
class Foo = Bar () () : ()
В Java это создаст имя Foo
в статическом глобальном пространстве имен, и будет искать Bar
в статическом глобальном пространстве имен и создать Bar
Foo
суперкласс. Даже в Ruby, который гораздо более динамичен, это все равно создаст статическую константу в глобальном пространстве имен.
В Newspeak эквивалентное объявление означает: создайте именованный метод getter Foo
и заставьте его вернуть класс, который ищет свой суперкласс, вызвав метод named Bar
. Примечание: это не похоже на Ruby, где вы можете поместить любой исполняемый код Ruby в качестве объявления суперкласса, но код будет выполнен только один раз при создании класса, и возвращаемое значение этого кода станет фиксированным суперклассом. Нет. Метод Bar
вызывается для каждого поиска метода!
Это имеет некоторые глубокие последствия:
- поскольку миксин в основном является классом, который еще не знает своего суперкласса, а в Newspeak суперкласс является динамическим вызовом виртуального метода, и, следовательно, неизвестен, каждый класс автоматически также является миксином. Вы получаете миксины бесплатно.
поскольку внутренний класс - это просто вызов метода, который возвращает класс, вы можете переопределить этот метод в подклассе внешнего класса, поэтому каждый класс является виртуальным. Вы получаете виртуальные занятия бесплатно:
class Outer {
class Inner { /* … */ }
}
class Sub extends Outer {
override class Inner { /* … */ }
}
новояз:
class Outer = () (
class Inner = () () : ()
) : ()
class Sub = Outer () (
class Inner = () () : ()
) : ()
Поскольку суперкласс является просто вызовом метода, который возвращает класс, вы можете переопределить этот метод в подклассе внешнего класса, у внутренних классов, определенных в суперклассе, может быть другой суперкласс в подклассе. Вы получаете наследование иерархии классов бесплатно:
class Outer {
class MyCoolArray extends Array { /* … */ }
}
class Sub extends Outer {
override class Array { /* … */ }
// Now, for instances of `Sub`, `MyCoolArray` has a different superclass
// than for instances of `Outer`!!!
}
новояз:
class Outer = () (
class MyCoolArray = Array () () : ()
) : ()
class Sub = Outer () (
class Array = () () : ()
) : ()
и, наконец, самое важное для этого обсуждения: поскольку (кроме тех, которые вы определили в своем классе, очевидно) вы можете вызывать методы только в своем лексически включающем классе (ах) и своем суперклассе (ах), самом внешнем классе верхнего уровня. не может вызывать любые методы на всех , кроме тех, которые явно инжектированные: класс верхнего уровня не имеет класса ограждающих методы которого он мог бы назвать, и она не может иметь суперкласса, кроме одного по умолчанию, потому что объявление суперкласса является вызов метода, и это , очевидно , не может перейти к суперклассу (это являетсясуперкласс), и он также не может перейти в лексически заключенный класс, потому что его нет. Это означает, что классы верхнего уровня полностью инкапсулированы, они могут получить доступ только к тому, что им явно вводят, и им вводят только то, что они явно запрашивают. Другими словами: классы верхнего уровня являются модулями. Вы получаете всю систему модулей бесплатно. Фактически, чтобы быть более точным: классы верхнего уровня являются объявлениями модулей, его экземпляры являются модулями. Таким образом, вы получаете модульную систему с параметрическими объявлениями модулей и первоклассными модулями бесплатно, что многие, даже очень сложные, модульные системы не могут сделать.
Чтобы сделать все эти инъекции безболезненными, объявления классов имеют необычную структуру: они состоят из двух объявлений. Одним из них является конструктор класса, который является не конструктором, который создает экземпляры класса, а конструктором, который создает среду, в которой выполняется тело класса. В Java-подобном синтаксисе это будет выглядеть примерно так:
class Foo(platform) extends Bar {
Array = platform.collections.Array
String = platform.lang.String
File = platform.io.File
| // separator between class constructor and class body
class MyArray extends Array { /* … */ }
// Array refers to the method defined above which in turn gets it from the
// platform object that was passed into the class "somehow"
}
новояз:
class Foo using: platform = Bar (
Array = platform collections Array
String = platform streams String
File = platform files ExternalReadWriteStream
) (
class MyArray = Array () () : ()
) : ()
Обратите внимание, что способ, которым программист Newspeak действительно собирается увидеть класс (ы), выглядит следующим образом:
Я даже не могу начать делать это справедливо. Вам придется поиграть с этим самостоятельно. Гилад Брача выступил с парой докладов о различных аспектах системы, в том числе о модульности. Он дал очень длинную (2 часа) речь , первый час которой - подробное введение в язык, включая историю модульности. Глава 2 платформы программирования Newspeak посвящена модульности. Если вы просматриваете Newspeak на Squeak - Руководство для недоумевающих (aka Newspeak-101) , вы почувствуете систему. Newspeak by Example - это живой документ (т.е. он работает внутри порта Newspeak-on-ECMASCript, каждая строка кода редактируема, каждый результат проверяем), демонстрирующий основной синтаксис.
Но на самом деле, вы должны поиграть с этим. Он настолько отличается от всех основных и даже неосновных языков, что его трудно объяснить, его нужно испытать.