Преимущества и недостатки структурирования всего кода с помощью классов и компиляции в классы (например, Java)


13

Изменить: мой язык допускает множественное наследование, в отличие от Java.

Я начал проектировать и разрабатывать свой собственный язык программирования для образовательных, развлекательных и потенциально полезных целей.

Сначала я решил основать его на Java.

Это подразумевает, что весь код будет написан в форме классов, и этот код компилируется в классы, которые загружаются виртуальной машиной.

Однако я исключил такие функции, как интерфейсы и абстрактные классы, потому что я не нашел в них необходимости. Казалось, что они применяют парадигму, и я бы хотел, чтобы мой язык этого не делал. Я хотел сохранить классы как модуль компиляции, потому что это казалось удобным для реализации, знакомым, и мне просто понравилась идея.

Затем я заметил, что я в основном остался с модульной системой, где классы можно использовать либо как «пространства имен», предоставляя константы и функции с использованием staticдирективы, либо как шаблоны для объектов, которые должны быть созданы («фактическое» назначение классов). на других языках).

Теперь я задаюсь вопросом: каковы преимущества и недостатки использования классов в качестве модулей компиляции?

Кроме того, любые комментарии к моему дизайну будут высоко оценены. Информационный пост на моем языке можно найти здесь: http://www.yannbane.com/2012/12/kava.html .


1
Если классы также включают пространства имен, которые устраняют неоднозначность всех идентификаторов в классе, то у вас есть полностью автономный модуль компиляции. Этот класс может быть успешно скомпилирован при условии, что все зависимости от других классов могут быть удовлетворены либо путем компиляции, либо путем ссылки на скомпилированный класс в сборке. Такая атомарность должна иметь очевидные преимущества.
Роберт Харви

Примечание: если вы удаляете абстрактные классы и интерфейсы, вы заставляете людей использовать наследование для подтипирования и полиморфизма. Это должно привести к ужасному коду. Кроме того, если вы не добавите множественное наследование (и не решите связанные проблемы), оно будет невероятно ограничено.

1
@delnan: На самом деле, вы все равно можете использовать композицию для создания функциональности.
Роберт Харви

2
@RobertHarvey Я предполагаю, что вы говорите об ограничениях из-за отсутствия множественного наследования. Да, можно подражать этому с достаточным составом, но я вряд ли считаю это приемлемым. Например, объект, который обычно реализует два интерфейса, должен был бы быть реализован дважды, в подклассах различных базовых классов (и хотя обе реализации могут делегировать общему классу, это все еще куча лишнего кода, и вы не можете легко повернуть экземпляр одного в экземпляр другого).

@delnan: Что не так с использованием наследования для подтипирования и полиморфизма? Это то, что наследство для ...
Мейсон Уилер

Ответы:


6

Каковы преимущества наличия классов в качестве модулей компиляции?

Это может уменьшить сложность языка. Нет необходимости в разных конструкциях, все обрабатывается одинаково. В определенных проектах (хотя, кажется, не в вашем) вы выигрываете от отсутствия статики и проблем дизайна, с которыми они, как правило, сталкиваются (проблемы порядка инициализации, ограничения параллелизма, неловкость с классами обобщений / типов). Это также допускает некоторые преимущества концепции модуля, такие как изолированные экземпляры модуля для песочницы или распараллеливания; и типизацию модулей, когда зависимости соответствуют некоторому интерфейсу, и можно реализовать весь экземпляр модуля и реализовать его.

Тем не менее, концепция имеет больше проблем, чем нет. Реально, вы не можете относиться ко всему одинаково, так как классы «верхнего уровня» нуждаются в специальных правилах, таких как наличие конструктора по умолчанию (иначе вы столкнетесь с нечетными проблемами, которые приводят их в движение). Модульность модулей компиляции также становится очень неудобной. Как класс даже ссылается на других, когда они просто классы? Как обрабатываются эти зависимости и как вы определяете правильный порядок раскрутки классов? Как убедиться, что повторяющиеся ссылки на классы повторно используются различными частями приложения (или как вы справляетесь с дублирующимися экземплярами, если вам нужна эта семантика)?

Изучив его, я столкнулся с множеством проблем с зависимостями, правильной областью определения и проблемами с инициализацией. В конечном итоге вы сталкиваетесь с проблемами, которые делают «классы верхнего уровня» особенными, и со многими ограничениями, заставляющими их работать, в конечном итоге формируете их в простые пространства имен.


Я планирую иметь только один класс высшего уровня Object. Я понимаю, что мне, вероятно, понадобится какое-то особое поведение для этого, но пока это единичный случай, я в порядке с этим. Я не верю, что у меня будут проблемы с зависимостью. Есть набор классов, которые загружаются при запуске виртуальной машины, некоторые из них реализованы изначально (класс System), но все они наследуются от Object. Как только все загружено, KVM загружает класс, который ему было поручено загрузить, и вырабатывает зависимости. Однако мне интересно, какие проблемы представляют статики?
Jcora

@yannbane - я не имею в виду object, я имею в виду классы, которые ведут себя как модули, а не как внутренние классы, которые не обязательно являются открытыми вне их модуля компиляции. «Выработка зависимостей» превращается в гнездо гигантского шершня в деталях, если вы хотите какое-либо поведение в стиле DLL; YMMV. Что касается статики .
Теластин

Такое модульное поведение будет достигаться за счет использования статических методов / переменных, верно? Плохо ли создавать класс, в котором есть только статические члены и методы, вместо того, чтобы создавать класс, для которого можно создать экземпляр? Я видел эту статью, однако, я не думаю, что она применима к постоянным статическим членам или статическим методам. Например, я не вижу ничего плохого в создании Mathкласса, который на самом деле является модулем со статическими методами и постоянным статическим двойным членом, вызываемым Pi.
Jcora

@yannbane - Нет, не совсем. Модули - это модули, потому что они создаются. В противном случае у вас просто есть пространства имен в стиле C ++. Как только вы ограничите классы верхнего уровня пространствами имен в стиле C ++, они больше не будут классами.
Теластин

Хм, я все еще в порядке и не вижу проблемы с созданием модулей с классами. И да, модули действуют как пространства имен, особенно модули Python.
Jcora

4

Вместо того, чтобы отвечать на этот вопрос, я поднимусь на один уровень выше и предложу изучить MIT OpenCourseWare , в частности 6.035 (Computer Language Engineering). Это объяснит всю проблематику, так что у вас не будет соблазна задавать подобные вопросы снова.

Компьютерная инженерия

Единственным предварительным условием является Java.

http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-035-computer-language-engineering-spring-2010/lecture-notes/

Описание курса

В этом курсе анализируются проблемы, связанные с реализацией языков программирования более высокого уровня. Охватываемые темы включают в себя: основные понятия, функции и структуры компиляторов, взаимодействие теории и практики и использование инструментов при создании программного обеспечения. Курс включает в себя проект для нескольких человек по разработке и реализации компилятора.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.