OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Воскресенье, 28 Апрель, 2024 00:08

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 19 ] 
Автор Сообщение
 Заголовок сообщения: ООП в КП
СообщениеДобавлено: Понедельник, 05 Февраль, 2007 09:26 

Зарегистрирован: Четверг, 01 Июнь, 2006 11:14
Сообщения: 240
Здравствуйте!
В нашем университете в курс программирования читается сначала Паскаль (тут узнаем основные алгоритмические конструкции, работаем с массивами, графикой и тд), затем Delphi6(здесь знакомимся со средой, учимся создавать интерфейс пользователя). Сам процесс обучения строится следующим образом: студентам раздаются методички и они по ним выполняют лабораторные задания, а преподаватель их принимает, задает вопросы и дает дополнительные задания. Для наших преподавателей такая схема очень удобна. Наша группа закончила Паскаль и будет переходить на Delphi. Я рассказал нашему преподавателю о КП, и предложил провести пару практических занятий с использованием КП. При чем, тк в основном в Delphi мы будем составлять интерфейсы и работать с компонентами формы, то особого смысла несколько занятий делать это на КП нету. Поэтому мне предложили выбрать тему, которая в нашем курсе не рассматривается – ООП. И раскрыть ее на КП(1 на введение, как работать в ББ, и 2-3 на раскрытие темы). Сам я ООП еще не знаю. Попытался поискать информацию об ООП в Обероне, везде рассказывается об отличиях со стандартным взглядом (классы, объекты), а так что бы с «нуля» не нашел. Получается, что бы понять ООП в Обероне нужно сначала изучить его в каком-нибудь промышленном языке…
Возникают следующие вопросы:
Возможно, я плохо искал, и уже есть учебники (книги, статьи) по КП в которых раскрывается ООП?
Интересны: сам материал по ООП, а так же показательные примеры, где ООП востребовано.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ООП в КП
СообщениеДобавлено: Понедельник, 05 Февраль, 2007 10:47 

Зарегистрирован: Четверг, 03 Август, 2006 16:28
Сообщения: 182
___ писал(а):
Сам я ООП еще не знаю. Попытался поискать информацию об ООП в Обероне, везде рассказывается об отличиях со стандартным взглядом (классы, объекты), а так что бы с «нуля» не нашел. Получается, что бы понять ООП в Обероне нужно сначала изучить его в каком-нибудь промышленном языке…
Возникают следующие вопросы:В
озможно, я плохо искал, и уже есть учебники (книги, статьи) по КП в которых раскрывается ООП?
Интересны: сам материал по ООП, а так же показательные примеры, где ООП востребовано.


Если надо изучить ОПП с самого нуля, то можно начать с девятой главы руководства к Borland Pascal:

http://zeus.sai.msu.ru:7000/programming/bp70_ug/bp70ug_09.shtml

На мой взгляд, это лучшее введение в предмет. После этого разобраться с ООП в КП особого труда не составит - отличия от Паскаля там не очень велики.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Понедельник, 05 Февраль, 2007 11:29 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Добавляю:
если по-английски читаете, то Н. Вирт "Programming In Oberon", последняя глава "Object-Oriented Programming" - там немного, самая суть ООП, как оно видится в Оберонах. Что изменилось - в Оберон-2 и соотв. в КП введены обычные методы - процедуры, связанные с типами, а Вирт в первом Обероне обходится без них, полями типа : PROCEDURE (), которые инициализируются указателями на процедуры, как обработчики событий у компонентов в Дельфи - у этого подхода и свои плюсы в большей гибкости, и свои минусы в меньшем удобстве использования.
Здесь можете скачать Programming In Oberon:
http://oberoncore.ru/index.php?option=c ... 6&Itemid=8

Суть ООП, в принципе, проста.
Обычно в учебниках выделяются такие его "киты", как:
1) Инкапсуляция
2) Наследование
3) Полиморфизм.
Так вот - инкапсуляция в Оберонах реализуется на уровне модулей, т.е. класс как тип данных и модуль как инкапсулирующий блок строго разделены (как и в Дельфи, кстати).

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

Полиморфизм обозначает, что при обращении рыба.Плыть() реальная реализация процедуры Плыть() при компиляции еще неизвестна. Происходит динамическое или позднее или виртуальное связывание (по всякому говорят), т.е. вызов конкретной процедуры произойдет на этапе выполнения в зависимости от реального типа переменной, которая была передана в данную точку программы.
Т.е. полиморфизм дает виртуализацию кода. Что такое виртуализация? Это неопределенность на этапе компиляции, когда реальное поведение блока кода до конца определяется только в момент его выполнения.

А теперь самая суть ООП - посмотрите на расширение типа данных и на полиморфизм. Суть в том, что ООП позволяет писать код (процедуры и целые модули), которые работают с данными, еще неизвестными в момент написания. Кто угодно может ввести через какое угодно время новые типы рыб, а наш код будет так же хорошо с ними работать, его не потребуется переписывать, а при правильном проектировании - даже перекомпилировать. Т.е. ООП позволяет расширение систем без изменения существующего кода. Вот и все! В этом предложении - вся суть ООП. ПРочтете в какой-нибудь "макулатуре", что ООП - это "наличие в языке классов и объектов" - выкидывайте эту макулатуру сразу, потому что очень многие языки являются объектно-ориентированными без наличия классов и объектов (кроме Оберонов- Ada, далее - языки функционального программирования, напр. LISP - и т.п.)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Понедельник, 05 Февраль, 2007 11:35 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Примеры прикладного ООП - наследования каких-нибудь объектов типа геометрических фигур, транспортных средств - да чего угодно - можно найти в любой литературе.

Техническое применение ООП в Оберонах и не только я затрагивал в статье "Некоторые идеи архитектуры Оберон-систем": http://oberoncore.ru/index.php?option=c ... &Itemid=22
Она будет, наверное, сложноватой, что непонятно - спрашивайте, потом что-то самое главное сможете взять для лекций.

А ниже еще - кое-что из истории ООП в изложении одного знающего товарища с оберонских форумов DelphiKingdom:
Цитата:
Дело в том, что попыток сформулировать, что же такое Оберон-технология (прошу заметить не язык и не система, а именно вынесенная в заголовок технология) было тут не мало. Но я уловил единственное реальное отличие от других систем: базовое понятие модуля, как единицы языка, единицы компиляции и единицы загрузки в одном лице. Да еще и с автоматическим динамическим контролем корректности вызовов.

В чем суть Оберона я уже сформулировала: модуль + расширение RECORD-типа. А динамика загрузки-выгрузки - побочная вещь.

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

Тони Хоар, один из ближайших друзей и соратников Вирта, называл это концептуальной экономией (conceptual economy). И наряду с надежностью и эффективностью считал очень важным свойством языка программирования.


Готов выслушать Вашу формулировку Оберон-технологии.

Боюсь, к этому не готова. Есть несколько разных Оберон-языков. Они исповедуют несколько отличные вещи. Поэтому корректнее было бы говорить об Оберон-технологиях, во множественном числе. И не удивляться, что в каких-то моментах они могут противоречить или вступать в конфликт друг с другом. По крайней мере, для пользы дела удобнее считать именно так, пока убедительно не доказано обратное.

ООП возникло дважды из двух разных классов задач.
Первый раз это было как раз имитационное моделирование - в Симуле67 было введено понятие класса и объекта, имеющего не только поля, но и схему поведения.

Если позволите, я бы это прокомментировала. В основе ООП лежит концепция класса. Откуда возникло это слово и сама идея? Разумеется, Smalltalk не был тут первопроходцем. Первым языком, в котором слово class, обозначающее ту концепцию, которая близка нашему нынешнему понимаю ООП, была Simula 67. Здесь Снегурочка с Вами готова согласиться. Но дело в том, что идея класса была сформулирована и реализована несколько раньше - в языке Simula I. Там уже были activity (классы) и process (объекты). Кристен Нигаард и Оле-Йохан Дал еще тогда заложили идею порождения объектов, каждый из которых суть данные плюс связанные с ними операции, правда, тогда еще без наследования.

В 1965 г. в ALGOL Bulletin вышла важнейшная работа Тони Хоара, которая называлась просто "Record Handling". В ней Хоар обобщил опыт других языков и предложил идею record class, объединив запись - record (известной по PL/I и COBOL) со ссылкой - reference (она была предложена Виртом в 1965 г. в его первом языке Euler и двумя годами ранее в языке CPL из английского Кембриджа).

Как признавались Нигаард и Дал в своих воспоминаниях о создании Симулы, именно осенью 1966 г. они тщательно изучали работы Хоара (вслед за первой вышла в марте 1966 г. и Further Thoughts on Record Handling). Они искали способ "прикрутить" понравившуюся идею record class к своей Симуле. И пришли к выводу, что ее можно сформулировать как process class, убрав слово process. Т.е. оставить просто class. Правда, reference там были в неявном виде.

В 1972 г. в Советском Союзе в изд-ве "Мир" вышел сборник "Языки программирования", где были опубликованы переводы докладов на Летней школе NATO по языкам программирования, которая прошла в 1966 г. в Виллар-де-Ланс (Франция). Если сможете его раздобыть, рекомендую внимательно изучить работу Хоара "Обработка записей" (Record Handling). Несмотря на не очень хороший перевод почитать очень даже стоит. Работа занимает примерно 60 страниц. Из нее понятно, откуда росли ноги ООП и что закладывалось в основу той самой Симулы-67, от которой обычно и принято вести отсчет эре ООП. В том же сборнике есть и столь же объемная статья Оле-Йохана Дала о Симуле. Сам Дал вместе с Нигаардом в качестве источника идей Симулы-67 упоминали именно эту тройку работ Хоара (включая и его доклад на школе NATO).

Второе открытие ООП связано с задачей построения оконного пользовательского интерфейса и языком Смолтолк. На этой задаче большинству студентов объясняют принципы ООП.

Собственно, это детище Алана Кея и дало реальный импульс моде на ООП, которая переросла потом во всеобщую "ООПсовизацию" программирования. Алан Кей, в отличие от большинства из нас, хорошо был знаком с ранними работами Никлауса Вирта, и с большим интересом относился, в частности, к тому же языку Euler, где была заложена динамическая типизация в рамках алголоподобного языка.

Поскольку сей факт известен очень немногим, приведу точные цитаты (дело было в апреле 1993 г. в американском Кембридже на конференции HOPL-II, сразу после доклада Вирта об истории разработки Паскаля):

Allen Kay: Your thesis and Euler were going in a pretty interesting direction. Why did you go back to more static languages?

Niklaus Wirth: For a thesis topic you have to do something that is new and original, you are expected to explore new ways. Afterwards, as an engineer, I felt the need for creating something that is pragmatic and useful.

В основу Паскаля были положены идеи Хоара о record handling. Но даже без намека на ООП. В Modula и Modula-2 вошли идеи Симулы по моделированию на основе процессов, хотя облечено это было в концепцию модуля из языка Mesa. В Обероне Вирт по сути вернулся к первоистокам: record + reference (но уже и ссылки на procedure) и дали фундамент для ООП без использования самого ООП. Круг замкнулся.

Таким образом, Оберон помимо того, что был квинтэссенцией Паскаля и Модулы, вобрал в себя идеи Хоара, Euler и Simula.



Ответ на >сообщение 1771< (AVC)
___________________________

Насчет модуля, кажется, понятно.

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

А в чем принципиальное различие между расширением типа и наследованием?

Вопрос непростой. Помимо чисто "идейно-психологического" различия (математическое понятие против социально-антропологического) есть и кое-что еще. Наследование (inheritance) устанавливает отношение наследования (нерефлективное, несимметричное, но транзитивное) между двумя сущностями - классами. Строго говоря, из наследования не вытекает, что "наследник" должен в точности сохранять структуру "наследодателя", лишь дополняя ее, и безболезненно подменять "наследодателя" везде, где тот ранее использовался.

У Вирта расширение типа (type extension) строится на понятии подтипизации (subtyping). Есть тип (расширяющий тип), есть его подтип (расширяемый тип). Принцип подстановки (Liskov substitution principle), выдвинутый Барбарой Лисков в 1993 г., говорит о том, что S является подтипом типа T, если для любого истинного q(t) следует, что истинно и q(s).

Если не ошибаюсь, в Eiffel при наследовании можно не только модифицировать, но и даже удалять свойства, унаследованные от базового класса. В C++, например, есть приватное наследование (private inheritance), нарушающее принцип подстановки и подтипизацию.

Вообще говоря, имеет смысл воспринимать type extension в Обероне с позиции record class Хоара, а не process class Нигаарда-Дала. Здесь больший уклон в данные, а не в операции. Хотя при наличии в Обероне процедурных типов, через которые и реализуются методы, никто не запрещает все перевернуть с ног на голову.
Снегурочка



Ответ на >сообщение 1856< (Сергей Перовский)
___________________________

объектный подход удобен при создании сложных систем, имитационное моделирование первым потребовало создания ОО инструмента потому, что занималось только сложными системами. Потребовалось еще 25 лет для осознания, что ООП пригодно для большинства сложных систем, что это не узкоспециализированный инструментарий для отдельного класса задач.

А следует ли из этого, что ООП пригодно для большинства простых систем? А если нет, то почему языки полностью "погружают" в ООП, как, например, Java?

Что касается понимания областей применимости ООП на заре его появления, то не скажу за Нигаарда и Дала, которые действительно в основном работали с имитационным моделированием, но по Хоару это не совсем так (цитирую по работе Record Handling из Летней школы NATO 1966):

Фундаментальная особенность нашего понимания мира заключается в том, что мы систематизируем свой жизненный опыт, представляя его в виде отдельных понятий или объектов (столы и стулья, банковские займы и алгебраические выражения, многочлены и люди, транзисторы и треугольники и т.п.), и наше мышление, язык и действия основываются на обозначении, описании и манипуляциях с этими объектами, с каждым в отдельности или в связи с другими объектами. Если мы хотим решить задачу на компьютере, то часто нужно построить в нем модель того аспекта реального или воображаемого мира, к которому будет применяться алгоритм решения задачи. В такой модели каждый объект исследования должен быть представлен некоторой величиной, которая "доступна" программе и может быть использована ею в процессе работы. Назовем такую величину записью (record). Каждый объект, представленный в запоминающем устройстве компьютера в виде записи, будет обладать одним или более атрибутами (attributes), с которыми и приходится иметь дело при решении задачи. Обычно эти свойства выражаются простыми значениями соответствующего типа. <...>

Объекты реального мира удобно классифицировать с помощью некоторого числа взаимно исключающих классов (classes), причем каждый класс обозначается некоторым собирательным именем, таким, как "человек", "банковский заем", "выражение" и т.д. <...>

Если программа выполнялась уже в течение некоторого времени, то может случиться так, что требуется сегмент расширения, а единственные доступные сегменты находятся в опасной близости к магазинной памяти. При подобных обстоятельствах целесообразно воспользоваться процедурой автоматического собирания свободных участков памяти, подобной той, которая описана Маккарти (1960).<...>

В реальных условиях часто разбивают класс объектов на несколько взаимно исключающих подклассов (subclasses). Например, класс позвоночных можно разбить на такие подклассы, как млекопитающие, пресмыкающиеся, птицы и рыбы...
Класс записей (record class), который разбивается на подклассы, называется составным; класс или подкласс, который не является составным, называется простым. Ссылочные переменные могут, согласно их описаниям, указывать на все записи составного класса или же их область действия может быть ограничена каким-то одним определенным подклассом.<...>

Если областью действия ссылочной переменной является, согласно ее описанию, составной класс, то программист может пожелать на некотором этапе выполнения программы определить, какому из возможных подклассов фактически принадлежит запись, на которую ссылается в настоящее время эта переменная. Этого можно достигнуть с помощью специальной конструкции, называемой различитель класса записи (record-class discriminator). <...>

Расширение определения знаков операций для действий над ссылками на записи новых типов называют перегрузкой (overloading). Впервые идея перегрузки была предложена Дж.Маккарти...

Как видно из этого текста, 40 с лишним лет назад Хоар достаточно подробно описал идеи ООП, при этом ни о каком ограничении сферой имитационного моделирования речи не идет. Хоар еще указал в своей работе такие языки обработки "ООП"-записей, как Lisp, Simula I и PL/I.

Вирт в Паскале интерпретировал идеи Хоара через указатели, записи и вариантные записи. Спустя полтора десятка лет после Паскаля он пришел к выводу, что это надобно делать через type extension с запретом вариантных записей (лобовой реализации составных классов). В остальном и автоматическая сборка мусора, и наследование, и полиморфизм (без явного использования этих терминов) были Хоаром озвучены. Было это до появления Simula 67.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Понедельник, 05 Февраль, 2007 19:12 

Зарегистрирован: Четверг, 01 Июнь, 2006 11:14
Сообщения: 240
после онакомления с
http://zeus.sai.msu.ru:7000/programming ... g_09.shtml
и
"Некоторые идеи архитектуры Оберон-систем"
появились некоторые вопросы
но самое важное(больше половины вопросов из-за того что запутался что есть класс и объект)
первоначально я понял так:
typeExp = record {тип записи - класс}
var
MyTypeEx: typeEx {экземпляр типа записи typeEx - объект}

по аналогии с типом переменной и конкретной переменной
если это так, то что такое "экземпляр объекта" в статье?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Понедельник, 05 Февраль, 2007 21:49 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Да, Вы все правильно поняли!
"Экземпляр объекта" - это просто ляп, опечатка...
Экземпляр типа записи = объект, все верно Вы поняли.
Экземпляр может быть статической переменной, может быть динамически размещен.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вторник, 06 Февраль, 2007 09:55 

Зарегистрирован: Четверг, 01 Июнь, 2006 11:14
Сообщения: 240
Илья Ермаков писал(а):
Экземпляр типа записи = объект

тогда озвучу оставшиеся вопросы:
1
http://zeus.sai.msu.ru:7000/programming/bp70_ug/bp70ug_09.shtml
"Ответом заключается в том, что при всякой возможности для доступа к полям данных должны использоваться методы объекта"

но так и не поясняется почему нежелательно обращаться к к полям напрямую...

все остальные вопросы по разделу "Особенности ООП в Оберонах"
хотя некоторые из них покажутся наивными я понимаю, что статья расчитана на более подготовленного читателя
2
"2) возможность связывания поведения с объектом данных, при этом каждый экземпляр данных сам «знает» свое поведение."
""Для связывания процедур с объектами использовались поля процедурного типа, то есть,никакой специальной синтаксической поддержки методов не вводилось.
Первым достоинством такого подхода является более сильная виртуализация — связывание вызова может варьироваться не только в зависимости от типа, но и от конкретного экземпляра объекта."

т.е. у двух объектов одного класса могут быть разные методы?
3
TYPE
Figure = RECORD
color: INTEGER
Square: PROCEDURE (VAR f: Figure): REAL
END;
Rectangle = RECORD (Figure)
x0, y0, x1, y1: REAL
END;

в этом примере непонятно почему строка:
Square: PROCEDURE (VAR f: Figure): REAL
описывается метод класса, где входной параметр сам класс?
4
TYPE
Figure = RECORD
color: INTEGER
END;
Rectangle = RECORD (Figure)
x0, y0, x1, y1: REAL
END;
PROCEDURE (VAR f: Figure) Square (): REAL
BEGIN
RETURN 0
END Square;
PROCEDURE (VAR r: Rectangle) Square (): REAL;
BEGIN
RETURN ABS(r.x1 - r.x0) * ABS(r.y1 - r.y0)
END Square;

т.е. когда мы создаем класс мы не указываем какие у него есть методы?
и если например не создавать PROCEDURE (VAR f: Figure) Square (): REAL то у класса Rectangle будут новыми не только поля x0, y0, x1, y1, но и метод Square?
5
"ABSTRACT — аналог EXTENSIBLE, запрещающий создание экземпляров типа, либо объявляющий сигнатуру связанной процедуры без тела"
зачем нам класс из которого мы не можем создать объект?
т.е. как мы можем использовать сам класс не создавая из него объект?
6
"NEW — маркирует процедуру, первый раз введенную в иерархии расширения, позволяет избежать опасной ошибки, когда в одном из базовых типов вводится связанная процедура, совпадающая с уже существовавшей процедурой в расширенном типе."
т.е. классу предку добавляют процедуру с именем которое уже используется у класса потомка?
почему это будет ошибкой?

дальше к сожалению очень многое становится непонятным, т.к. в голове еще толком не улеглись ABSTRACT, EXTENSIBLE, EMPTY, LIMITED, NEW

---------------------------------------------------------------------------------
так же нашел опечатку:
"Такая позднее связывание еще называют виртуализацией кода."


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вторник, 06 Февраль, 2007 12:54 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
1) Принцип инкапсуляции - сокрытия подробностей внутреннего устройства от клиента. Клиент может модифицировать поля только строго определенным образом, через методы, при этом метод может проверить, чтобы изменение значений было осмысленным. Совершенно открытые поля оставляются только у записей, у которых нет поведения, т.е. структур данных, не являющихся полноценными объектами.
В других языках приходится вводить пару методов - Get и Set.
В Обероне можно открыть поле только для чтения, а для изменения ввести методы. Иногда это серьезный плюс к быстродействию.

2) "т.е. у двух объектов одного класса могут быть разные методы? "
Именно так. Как, например, в Дельфи у двух компонентов одного типа TButton могут быть разные обработчики OnClick.

3) Так метод в стиле классического Оберона - это всего лишь процедурное поле, указатель на процедуру. А самой процедуре надо еще раз сообщать, для какого объекта она вызывается.
Т.е. был стиль вызова: object.Do(object, ...).
Не особенно удобно. Поэтому Мессенбеком в Обероне-2 и были введены связанные процедуры. Явный параметр в них остался, но его уже не нужно явно дублировать при вызове.

4) "т.е. когда мы создаем класс мы не указываем какие у него есть методы? "
"Создание класса", т.е. определение класса - это вся совокупность определений в модуле. Т.е. само описание структуры типа данных RECORD и затем - введенные связанные процедуры.
Убрать процедуру - это значит изменить тип. В частности, модули-клиенты сразу потребуют перекомпиляции, несовместимость.

5) Мы определяем ИНТЕРФЕЙС без реализации. А реализовать этот интерфейс предоставляем конкретным типам-расширениям.
Т.е. ABSTRACT-тип - своего рода разъем. Затем мы определим конкретные типы, реализующие эти разъемы и соединим их, при этом они ничего не будут знать о деталях реализации друг друга. Как в IBM PC - по стандартным разъемам можно подключить любую реализацию.
Подробнее в любой книжке по той же Делфи можете почитать, абстрактные классы применяются во всех распространенных ОО-языках.

6) Добавление предку процедуры с именем потомка - это ошибка.
Проектная ошибка. Потому что создатель типа-потомка предполагает, что он впервые ввел такую процедуру. А создатель типа-предка вводит свою, не зная, что такая уже есть. МОжет быть, эти процедуры вообще имеют разное назначение, только одинаковые имена. Такой путаницы допускать нельзя.
На практике, когда мы пишем модуль для широкого использования, единожды определив экспортированный тип, мы вообще не имеем права менять его "фасад", кроме внутренней реализации.

Да, еще, почитайте раздел хелпа Блэкбокса - "Что нового в языке".


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 15 Февраль, 2007 16:29 

Зарегистрирован: Четверг, 01 Июнь, 2006 11:14
Сообщения: 240
сегодня провел первое занятие в одной группе(завтра стоит пара у второй)
решил поделиться результатами-впечатлениями:
на первом занятии планировал ввести людей в среду ББ(после TP70)
проводил занятие так:

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

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

3 на следующем этапе приступили к написанию самой простой программы типа "привет"
рассматривая способы компиляции, выгрузки и запуска приложений
тут народ уже повеселел тк после тп70 интерфейс все же более приближен к винде, можно удобно копировать-вставлять без ограничений и неудобств дос режима
так же я использовал русификацию менюх и сообщений компилятора
соответственно вопросов, "где найти нужную команду" и "что это за ошибка" небыло (из курьезов: попытка избавления от ошибок путем стирания маркеров ошибок)
появилось много ошибок из-за регистрозависимости, в паскале об этом совсем не задумывались
так же подвел орг момент маленько
люди привыкли что тетради не нужны, и не записывали некоторые факты
соответственно потом не могли понять, почему после правки программы давя на кумандер программа не меняется
ну вообщем этот этап завершился всеми
завтра думаю сразу сподвигнуть достать тетради, моно и по др предмету и некоторые вещи все же надиктую

4 этап
тут я разделил их на 2 группы и дал задание каждой группе разобраться по справке с синтаксисом операторов (if loop for и case while repeat) и выяснить диапазоны типов integer и real с помощью встр. функций min max
а затем представить для второй группы результаты своих изысканий
соответственно я планировал подтолкнуть людей при некоторых непонятках обращаться в справку
ну и при выступлении, когда они должны были объяснить результат друг другу расчитывалось на то, что "чтобы объяснить другому нужно самому понять"
вообщем лаконичность сообщения языка позволило легко найти нужные разделы, но привело к затруднению при их расшифровке
этот этап оказался последним, 1 группа успела выполнить свои задания а вторая нет
решили что выступления перенесем на начало следующей пары
завтра попытаюсь с оптимизироваться и все же успеть провести и выступления

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

после пары преподаватель сказал мне, что бы я темп чуть помедленнее сделал, что торопиться не надо, количеством пар (3-4) он меня ограничивать не будет
(планировалось 1 пара на ввод в ББ и 3 пары на ООП)
таким образом на вникание в среду времени будет побольше
правда у меня появились маленькие сомнения, что ООП получится довести до каждого....(раньше его в курсе на нашем факультете небыло из соображений "сложно для студентов, да и не зачем")
но от идеи все же попытаться до людей это донести я не откажусь!

вообщем такие вот первые впечатления....


так же появились несколько разносортных вопросов:

1 в КП нету типа string, в место него предлагается array of char и модуль In
сегодня я этот вопрос не затрагивал
но после простого использования типа стринг, люди не воспримут с интузиазмом необходимость работы со строками заполняя их через циклы по букве...
может есть еще пути более приближенные к типу стринг?

2 "Так вот - инкапсуляция в Оберонах реализуется на уровне модулей, т.е. класс как тип данных и модуль как инкапсулирующий блок строго разделены (как и в Дельфи, кстати)."
т.е. для того, что бы продемонстрировать идею инкапсуляции сначало нужно посоставлять различные программы из разных модулей, и рассмотреть межмодульное взаимодействие?
или можно ограничиться тем что поля записей нельзя изменять напрямую, а только с помощью методов?

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 15 Февраль, 2007 17:01 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Поздравляю с дебютом! :-)

1) По поводу ARRAY OF CHAR - так в КП с ним можно делать все то же самое, что и со string в Паскале - сравнивать, складывать, умножать, присваивать. Только не забывать про оператор $.

2) Вообще говоря, для демонстрации инкапсуляции нужно именно несколько модулей. Потому что сокрытие полей происходит от кого? - от других модулей. Процедуры внутри одного модуля могут менять поля всех типов этого модуля.

3) Не инициализируются только локальные переменные процедур. Обнуляются только указатели - это необходимо для безопасности.
Инициализировать локальные переменные нужно в начале тела процедуры. А такие переменные, как счетчик FOR и т.п., инициализировать, ясное дело, не нужно вообще.
Те переменные, которые переиспользуются по нескольку раз (например, в каждом витке цикла), надо инициализировать на каждом витке цикла - и т.п.

Глобальные переменные модулей зануляются. Инициализировать их какими-то другими значениями можно из секции BEGIN модуля, которая выполняется при загрузке модуля в память.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 15 Февраль, 2007 18:16 

Зарегистрирован: Четверг, 03 Август, 2006 16:28
Сообщения: 182
___ писал(а):
т.е. для того, что бы продемонстрировать идею инкапсуляции сначало нужно посоставлять различные программы из разных модулей, и рассмотреть межмодульное взаимодействие?
или можно ограничиться тем что поля записей нельзя изменять напрямую, а только с помощью методов?


Наверное, не нужно. Достаточно просто сказать, что модуль - это "черный ящик", преднизначенный для выполнения какой-то конкретной задачи. Из этого ящика наружу "торчит" небольшое количество процедур, констант и переменных, с помощью которых эту задачу можно решить. Это - его интерфейс, а все остальное скрыто внутри "ящика". Это и есть инкапсуляция. Зачем это нужно? Затем, чтобы можно было свободно модифицировать "начинку" ящика, не меняя его интерфейс.

Это общий принцип конструирования сложных систем. Скажем, интерфейс у Windows 98 и Windows 2000 - идентичны, а "начинка" - принципиально отличается, фактически это две совершенно разные ОС. Но пользователю забивать этим голову не надо, и он легко пересядет с одной системы на другую.

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ООП в КП
СообщениеДобавлено: Четверг, 15 Февраль, 2007 20:51 

Зарегистрирован: Четверг, 03 Август, 2006 16:28
Сообщения: 182
Вот, кстати, простой пример использования инкапсуляции.
Допустим, мы написали модуль для обработки каких-то данных. Назовем его Processor. Данные для обработки он получает от модуля DataSource. Но сначала нам надо как-то отладить Processor, а для этого нужно сгенерировать данные с заранее известными свойствами. Для этого пишем модуль SimulatedData c тем же интерфейсом, что и DataSource, и подставим его в Processor вместо DataSource:

MODULE Processor;

IMPORT DataSource := SimulatedData;

Если нам потребуется брать данные с какого-то третьего источника, просто напишем для этого модуль DataSource2 и точно также подставим его вместо DataSource. Причем написать этот модуль можно поручить другому программисту - нам совершенно неважно, как он получение этих данных реализует. Главное, чтобы интерфейс модуля был тот же самый.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 22 Февраль, 2007 16:43 

Зарегистрирован: Среда, 16 Ноябрь, 2005 20:18
Сообщения: 37
Откуда: Украина, г.Киев
1). И всетаки в BP и Delphi можно создать инициализированые переменные.
Есть такой нюанс реализации. Для этого переменную обьявляют... в разделе CONST :shock: с явным указанием типа, т.е.
Код:
CONST MyVar: MyType = Value;

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

2). По поводу иницализации полей и инкапсуляции в CP полезно обратить внимание на такую вещь как директория (фабрика).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 22 Февраль, 2007 16:46 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Ага, это так называемые "типизированные константы". Есть такой маразм, что в настройках компилятора можно выставить галочку "Allow asignment to typed constants" - и тогда такие "константы" вообще можно будет изменять, как обычные переменные.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пятница, 23 Февраль, 2007 11:22 

Зарегистрирован: Четверг, 01 Июнь, 2006 11:14
Сообщения: 240
хм
уточнил некоторые относительно оргмомента...

1 основную часть заложенную в программу мы прошли(Паскаль), госы будут по нему, поэтому преподаватель так спокойно отдает время на КП
обычно в этом семестре проходят Делфи для расширения кругозора(курс называется даже чуть по другому), но можно и др вещи проходить
2 как раз вышла 3 часть лаб. работ по делфи... полностью посвященная ООП(у нас в универе для себя разрабатывают)

на нашем факультете 2 преподавателя ведущие программирование:
1 ведет (лекции у всех вначале)+практики(у половины), пишет лаб. работы по Делфи
2 ведет практики у второй половины
оба были на круглом столе с Виртом в 2005г
но идеей КП особо не зарядились


вообщем моя первоначальная цель: показать ООП на 4-5 занятиях и все, уже потеряла актуальность....

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

вообщем пока переосмысливаю...чего дальше делать
на пару недель то есть чем занять людей(знакомство со средой затянулось маленько))
а вот дальше пока толком и не ясно
буду искать интересные и показательные(с хорошими примерами) темы
ММП?)

PS тк педвуз, может в сторону школьной программы свернуть(в смысле показать то чем потом со школьниками можно заниматься)
пока еще слабо знаю среду, чтобы придумать с ходу
буду копать


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пятница, 23 Февраль, 2007 12:42 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Есть хороший пример демонстрации возможностей графического каркаса ББ.
Обсуждалось в этой ветке - viewtopic.php?t=241.

Разберитесь не спеша с предложенным решением, там, если не заметите, по ссылке http://blackbox.metasystems.ru/download ... raphic.odc был выложен исходник, в котором четыре или пять версий - в порядке последовательного усложнения.
В итоге для задачки, с которой человек мучался на Дельфи весьма долго, в ББ получилось решение в 300 строчек.
Разберитесь сами и покажите так же поэтапно этот пример на одном из занятий - будет смотреться очень эффектно. Я думаю, ваши преподы загорятся после этого :-) А если не загорятся - то спросите: слабо повторить на Дельфе?

Только в исходнике явно выделяйте нужную версию и выбирайте "Compile Selection", а то компилятор кушает все модули из документа подряд, и в результате скопилированной оказывается самая ранняя версия, лежащая в конце.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 01 Март, 2007 16:30 

Зарегистрирован: Четверг, 01 Июнь, 2006 11:14
Сообщения: 240
Илья Ермаков писал(а):
Есть хороший пример демонстрации возможностей графического каркаса ББ.

Пример посмотрел…удобно, что он показан в развитии, но задача больно специфическая…
Пока вопрос об нужности снял тем, что готовим учителей информатики и КП в школе хорош хотя бы лучшим синтаксисом основных конструкций)

Продолжая разбираться со средой, возникли еще пара вопросов:
1 придумал следующий простой пример для студентов:
Модуль решения кВ. ур. И пара модулей интерфейсов к нему (с выводом в рабочий журнал и на формы[диалоговая форма по модулю строится автоматически])

MODULE StudKvur;
IMPORT Math;

PROCEDURE ReshKvUr* (OUT m: ARRAY OF REAL; a,b,c: REAL): BOOLEAN;
VAR
i:INTEGER;
noerrors:BOOLEAN;
BEGIN
noerrors:=FALSE;

FOR i := 0 TO LEN(m)-1 DO
m[i]:=0
END;

IF (LEN(m)>=3) & (a#0) THEN
noerrors:=TRUE;
m[0]:=(b*b)-4*a*c;
IF m[0]=0 THEN
m[1]:=-b/(2*a);
m[2]:=-b/(2*a);
ELSIF m[0]>0 THEN
m[1]:=(-b+Math.Sqrt(m[0]))/(2*a);
m[2]:=(-b-Math.Sqrt(m[0]))/(2*a);
END;
END;

RETURN noerrors;
END ReshKvUr;

END StudKvur.

MODULE StudKvurEx;

IMPORT StdLog, StudKvur;

PROCEDURE Сказать*;
VAR
ar:ARRAY 3 OF REAL;
BEGIN
IF StudKvur.ReshKvUr(ar,1,2,0) =TRUE THEN
StdLog.Ln();
IF ar[0]<0 THEN
StdLog.String("Действительных корней нет");
ELSIF ar[0]=0 THEN
StdLog.String("Один действительный корнень: "); StdLog.Real(ar[1]);
ELSE
StdLog.String("Два действительных корненя: "); StdLog.Real(ar[1]);StdLog.String(' и ') ;StdLog.Real(ar[2]);
END;
ELSE
StdLog.String("Не удалось произвести вычисления!");
END;
StdLog.Ln();
END Сказать;

END StudKvurEx.

MODULE StudKvurExF;

IMPORT Dialog, StudKvur;
VAR
a*,b*,c*,x1-,x2-:REAL;
сообщение-:ARRAY 40 OF CHAR;

PROCEDURE Сказать*;
VAR
ar:ARRAY 3 OF REAL;
BEGIN
IF StudKvur.ReshKvUr(ar,a,b,c) =TRUE THEN
IF ar[0]<0 THEN
сообщение:="Действительных корней нет";
x1:=0;
x2:=0;
ELSIF ar[0]=0 THEN
сообщение:="Один действительный корень";
x1:=ar[1];
x2:=ar[1];
ELSE
сообщение:="Два действительных корня";
x1:=ar[1];
x2:=ar[2];
END;
ELSE
сообщение:="Не удалось произвести вычисления!";
x1:=0;
x2:=0;
END;
Dialog.UpdateReal(x1);
Dialog.UpdateReal(x2);
Dialog.UpdateString(сообщение);
END Сказать;

BEGIN

END StudKvurExF.



Идея показать, что сначала нужно разрабатывать решение задачи, а потом уже создавать реализацию интерфейса (хотя в процессе написания решения нужно будет проверять правильность логики…)[в пособии по Delphi у нас в основном примеры в которых больше кода уходит на взаимодействие с интерфейсом, и складывается впечатление, что мы строим интерфейс под задачу, а потом уже решаем саму задачу, причем получается решение интерфейсозависимое].
Если в StudKvur вместо OUT m: ARRAY OF REAL написать OUT m: ARRAY 3 OF REAL, то в StudKvurExF будет возникать ошибка: StudKvur.ReshKvUr(ar[тип не совпадает с типом формального VAR параметра],a,b,c)
Непонятно почему так нельзя…
Так же у одного из студентов возникло желание превратить это дело в exe фаил.
Пробовали так:
[кумандер]DevLinker.Link
ex1.exe := National Kernel$+ Files HostFiles Math StudKvur Dialog StudKvurExF
неработает))
чего добавить в модуль чтоб заработало непонятно…
2 начал разбираться с вьюшками (думаю с ними можно интересные примеры будет придумать), но тут столкнулся со следующим:
Часто в коде используется NEW, New
Почитав справку вот чего я понял:
Если мы просто создадим переменную, то она будет занимать место в памяти при запуске программы сразу, а если мы объявим указатель, то переменная будет размещена в памяти только если в программе будет выполнено NEW(имя указателя). Т.е. по большему счету это нужно для эффективности? Или есть еще какой смысл в них? (в курсе паскаля мы с указателями не работали…)
New же используется часто для создания экземпляра класса, стандартное название метода для таких ситуаций(?).
Получается, перед ООП нужно людей сначала познакомить с указателями? (тк если смотреть конкретные реализации, то в них New фигурирует часто)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 01 Март, 2007 17:46 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
1) Вы выбрали совершенно неудачный способ передачи параметров. Во-первых, для чего здесь использовать массив? Массив используется для хранения однородных элементов, вектора, а здесь у вас в него валится и дискриминант, и корни. Имело бы смысл использовать массив для корней, если бы их могло быть больше двух, а тут...
Дискриминант - это часть внутренней реализации процедуры решения кв. ур-я - и его не следует выносить наружу! У вас интерфейсный код узнает, есть ли корни, по значению дискриминанта, а должен всего лишь получить TRUE/FALSE - есть ли корни или нет.
А если мы захотим изменить реализацию процедуры ReshKvUr - и будем вычислять корни, ну, к примеру, численным методом (пусть и маразм), без вычисления дискриминанта? Что возвращать в m[0] будем?
Думаю, убедил, что так нельзя.
А как тогда? Да заведите вы три выходных атомарных параметра:
PROCEDURE ReshKvUr* (a,b,c: REAL; OUT exist: BOOLEAN; OUT x1, x2: REAL).
Возвращайте наружу через exist, есть ли корни, а в x1, x2 - сами эти корни (если дискриминант равен нулю, то все равно два корня, только равны между собой).
Теперь по поводу возвращаемого значения процедуры. Ну, самое первое - если процедура имеет OUT-параметры, то возвращаемое значение ей обычно не задают. Это так называемый принцип "чистоты функций". Т.е. если пишем функцию, которую можно будет использовать в выражениях, то она не должна ничего менять ни вокруг себя, ни в своих параметрах, а только возвращать значение (как функция в математике).
Т.е. в вашем варианте вместо возврата значения надо было бы заводить еще один OUT-параметр: OUT noErrors: BOOLEAN).
Однако если мы отказались от массива, то он стал не нужен.
Однако - подумаем, а зачем он нужен вообще? Просто для проверки правильности входных данных - что нам подали на входе массив верного размера? Я вам открою еще один секрет - проверку через IF и возврат ошибки для этих случаев не делают. Соблюдение всех условий по входным данным - так называемых предусловий - это обязанность того, кто процедуру вызывает. А на входе процедуры ставится проверка соблюдения этих предусловий - оператор ASSERT: для вашего случая было бы - ASSERT(LEN(m) >= 3). И все. Что произойдет, если процедуре подадут неверные данные? Попробуйте - увидите, что выскочит окошко сбоя - трепа. Все правильно - нарушение предусловия процедуры - это и есть сбой, и выполнение процедуры немедленно прерывается.

А явные коды результатов "успех-неуспех" используются в случаях, когда ошибка может быть где-то в окружении, когда это не сбой в самой программе. Ну например, не удалось подключиться к серверу или открыть файл. Тогда мы как-то можем обрабатывать ошибку. А если нам неверный массив подали - то что тут обрабатывать? Нужно немедленно прерывать выполнение программы, что и делает ASSERT...

В общем, осмыслите все сказанное - это как раз очень важные вещи. И хорошо, что появилась возможность все их разом объяснить на разборе конкретных ошибок...

Кстати, а можно еще вообще не возвращать явно "есть ли корни, нет ли корней". У типа REAL есть особое значение - бесконечность, неопределенность. Записывается как INF.
Просто, если корней нет, то вернем x1=x2=INF.
А код верхнего уровня будет проверять IF x1 # INF THEN корни есть ELSE корней нет END.

2)
Цитата:
Если в StudKvur вместо OUT m: ARRAY OF REAL написать OUT m: ARRAY 3 OF REAL, то в StudKvurExF будет возникать ошибка: StudKvur.ReshKvUr(ar[тип не совпадает с типом формального VAR параметра],a,b,c)
Непонятно почему так нельзя…

Вкратце - массивы должны быть одного типа. Однако у вас возникает вопрос - а почему же они не одного типа, если объявлены одинаково?
Это еще ничего не значит, если размерности двух массивов случайно совпали - они все равно принадлежат к разным типам (может быть, в одном хранятся одни физические величины, а в другом - другие, какая же тут совместимость?)
Чтобы массивы стали совместимы, нужно явно объявить общий для них тип:
Код:
TYPE
   Ответ = ARRAY 3 OF REAL;

PROCEDURE Resh (ответ: Ответ);
END Resh;

PROCEDURE Test;
  VAR отв: Ответ;
BEGIN
  Resh(отв)
END Test;

- вот так заработает.
Вдумайтесь еще раз, почему массивы одинаковой размерности по умолчанию все равно несовместимы. Ведь совпадение могло быть случайным, а массивы предназначались совсем для разных целей. Кто-то по ошибке его использовал, а затем я изменил размер массива в своей процедуре - и все, совпадение прекратилось, тот, кто моей процедурой поспешно воспользовался, остался в дураках...
Поэтому и нужно вводить явно специальный тип массива и потом его использовать.

А форма записи ARRAY OF.. - это открытый массив, он специально предназначен для написания процедур, обрабатывающих массивы переменных размеров.

3) С линковкой сейчас смотреть времени нет. Почитайте в Общих вопросах, там это обсуждалось. Вообще, для полной комплектации в EXE-файл надо линковать много модулей. Там в документации на DevLinker этот список есть, только добавьте National.
И все равно еще снаружи должны болтаться файлы ресурсов.
Чтобы собрать совсем один EXE, нужно потом применить еще DevPacker.
В общем, дело несложное (см. viewtopic.php?t=196), но немножко разбираться в среде нужно...

4) По поводу указателей.
Эээ, батенька, указатели нужно изучить, без них далеко не уедешь. Динамическое выделение памяти используется сплошь и рядом. Почитайте для начала любую книжку хоть по Турбо Паскалю, ну не объяснять же все это здесь... В самоучителе от Info21 (у нас в Документации) вроде бы это тоже было...

Цитата:
Т.е. по большему счету это нужно для эффективности? Или есть еще какой смысл в них?

Ни одно реальное приложение не знает, сколько и каких переменных ему понадобится в момент выполнения. Например, открылось новое окно с документом и графическим объектом - ему требуется память. Она выделяется динамически.

NEW - это оператор языка для выделения памяти.
А New.. и т.п. - это уже разнообразные самые обычные процедуры, которые создают новый объект оператором NEW, чего-то там ему инициализируют в полях, а затем возвращают указатель.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 01 Март, 2007 18:52 

Зарегистрирован: Четверг, 01 Июнь, 2006 11:14
Сообщения: 240
Илья Ермаков писал(а):
1) Вы выбрали совершенно неудачный способ передачи параметров.

согласен
хорошо, что еще не использовал его на самих парах)

Илья Ермаков писал(а):
Дискриминант - это часть внутренней реализации процедуры решения кв. ур-я - и его не следует выносить наружу! У вас интерфейсный код узнает, есть ли корни, по значению дискриминанта, а должен всего лишь получить TRUE/FALSE - есть ли корни или нет.

опять же согласен
раз процедура возвращает корни, то лишнее в ней ни к чему
если нужен дискриминант для каких-то целей, то наверно лучше отдельную процедуру-функцию выделить для нее в этом модуле
Илья Ермаков писал(а):
А если мы захотим изменить реализацию процедуры ReshKvUr - и будем вычислять корни, ну, к примеру, численным методом (пусть и маразм), без вычисления дискриминанта? Что возвращать в m[0] будем?

можно было бы возвращать -1 0 1
Илья Ермаков писал(а):
Думаю, убедил, что так нельзя.

убедили!
переделаю
Илья Ермаков писал(а):
Теперь по поводу возвращаемого значения процедуры. Ну, самое первое - если процедура имеет OUT-параметры, то возвращаемое значение ей обычно не задают. Это так называемый принцип "чистоты функций". Т.е. если пишем функцию, которую можно будет использовать в выражениях, то она не должна ничего менять ни вокруг себя, ни в своих параметрах, а только возвращать значение (как функция в математике).

понятно
сразу и остальным расскажу
если уж нужен пример с различными параметрами(по значению и по ссылке), и обычные процедуры и процедуры функции, то просто добавлю в пример процедуру-функцию вычисления дискриминанта
Илья Ермаков писал(а):
А на входе процедуры ставится проверка соблюдения этих предусловий - оператор ASSERT: для вашего случая было бы - ASSERT(LEN(m) >= 3). И все. Что произойдет, если процедуре подадут неверные данные? Попробуйте - увидите, что выскочит окошко сбоя - трепа. Все правильно - нарушение предусловия процедуры - это и есть сбой, и выполнение процедуры немедленно прерывается.

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

Илья Ермаков писал(а):
Т.е. в вашем варианте вместо возврата значения надо было бы заводить еще один OUT-параметр: OUT noErrors: BOOLEAN).
Однако если мы отказались от массива, то он стал не нужен.

если a=0, то возникает опять же ошибка
получается либо ассертом a проверять(перекладываем проверку на модуль интерфейса), либо оставлять noErrors
[либо, теоретически, создавать тип REAL без нуля и требовать его на вход, если такое возможно]
Илья Ермаков писал(а):
Кстати, а можно еще вообще не возвращать явно "есть ли корни, нет ли корней". У типа REAL есть особое значение - бесконечность, неопределенность. Записывается как INF.
Просто, если корней нет, то вернем x1=x2=INF.
А код верхнего уровня будет проверять IF x1 # INF THEN корни есть ELSE корней нет END.

опробую обязательно!

Илья Ермаков писал(а):
Вдумайтесь еще раз, почему массивы одинаковой размерности по умолчанию все равно несовместимы. Ведь совпадение могло быть случайным, а массивы предназначались совсем для разных целей. Кто-то по ошибке его использовал, а затем я изменил размер массива в своей процедуре - и все, совпадение прекратилось, тот, кто моей процедурой поспешно воспользовался, остался в дураках...
Поэтому и нужно вводить явно специальный тип массива и потом его использовать.

а)получается нужно создать такой тип в модуле решения
а на входе процедуры требовать именно его
тогда, что бы ее вызвать человеку явно придется сначало создать экземпляр типа из моего модуля а потом с ним уже лезть в процедуру
б)или использовать открытый массив на входе

второй вариант выглядит проще)
ну в данном примере мне массив уже не понадобится

Илья Ермаков писал(а):
Почитайте в Общих вопросах, там это обсуждалось.

точно
это я не досмотрел
темы такие часто встречал когда не нужны были)


Илья Ермаков писал(а):
4) По поводу указателей.
Эээ, батенька, указатели нужно изучить, без них далеко не уедешь.

хорошо, что выяснилось до того, как я дошел до ООП)

Илья Ермаков писал(а):
Ни одно реальное приложение не знает, сколько и каких переменных ему понадобится в момент выполнения.

...но ведь мы указатели все равно объявляем
т.е. предусматриваем их возможность появления
или от одного указателя можно кучу переменных объявить?...
буду разбираться)

спасибо за конструктивную критику!


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 19 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2024, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB