Все типы - классы

Просмотров: 37485

Можно долго программировать в PascalABC.NET в обычном стиле и не замечать, что все типы стали классами. Но в один прекрасный момент кто-то после имени переменной нажмет точку и ... получит список методов для этой переменной как объекта класса. Например, достаточно описать целую переменную

var i: integer;

и потом набрать в коде

begin
  i.

После точки всплывет окно с так называемыми экземплярными методами, применимыми к переменной i класса integer. Их всего 6, и на первых порах только один метод из них полезен. Это метод ToString, преобразующий значение i к строке:

var s: string;
s := i.ToString;

Точечная запись в самом начале обучения воспринимается в основном в штыки: слишком непосилен груз нового в обучении. Вам будут говорить: 1) это не Паскаль! 2) это только в этом дурацком .NET так! 3) объекты школьникам - это зло, а для студентов надо давать C++ 4) <здесь - ваша цитата>.

Но факт остается фактом - так писать можно, а значит, все равно так будут писать, и вряд ли это можно будет удержать. Ведь вспомнить имя стандартной функции

s := IntToStr(i);
будет куда как не проще. К тому же, в Delphi для ее использования модуль SysUtils подключать надо. А, да, забыл - есть еще процедура Str с двумя параметрами, один из которых - ссылочный - она еще в теме "Строки" проходится - где-то через полгодика. А здесь мы получили интуитивно понятную запись и сразу начали ее использовать:

Эту запись можно трактовать двояко. Можно считать, что мы даем команду ToString объекту i, и он по этой команде возвращает свое строковое представление. Можно считать, что объект i имеет в своем составе команду ToString и сам ее вызывает. Последняя идея мне нравится больше: все объекты - активные, каждый имеет свою систему команд и готов их вызывать в любой момент.

Здесь мы сталкиваемся с еще одним психологическим барьером: если даже тип integer - класс, то наверняка программа будет работать очень медленно, ведь в ма-аленькой переменной integer - столько методов! они наверняка все и замедляют! Увы - это неверно. На скорость работы программы наличие большого числа методов у объекта класса никак не сказывается.

Но - продолжим! Однажды начав исследовать методы классов, кто-то  обязательно наберет точку после имени типа, а не имени переменной:

integer.

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

Кроме статических методов, мы увидим также две константы:

integer.MaxValue
integer.MinValue

По названиям нетрудно догадаться, что они обозначают наибольшее и наименьшее значения для переменных типа integer. Знатоки скажут, что вместо integer.MaxValue проще написать MaxInt и будут правы - короче. Только подобные константы определены во всех числовых типах: real.MaxValue, byte.MaxValue, word.MaxValue и т.д. А длинная запись - ну, это не самое страшное. Разве для объяснения мы используем самые короткие слова? К тому же, понятно, что значение MaxValue связано именно с типом integer и ни с каким другим.

Среди статических методов класса integer выделяется метод Parse для преобразования строк в целые:

i := integer.Parse('345');

В переменную i, как мы догадываемся, попадет значение 345. Конечно, если мы подадим на вход методу Parse строку, не являющуюся числом, то возникнет исключение, его надо будет обрабатывать, либо использовать статический метод TryParse:

var b: boolean := integer.TryParse('345',i);

Не сможет преобразовать - так и вернет False. Короче, надо разбираться. Отложим пока.

Заметим, что наш алгоритм исследования статических и экземплярных методов класса integer напоминает действия маленького ребенка, исследующего мир: он ПРОБУЕТ ВСЕ и что-то у него получается. Это что-то он будет повторять много раз, потому что ему понравилось, а непонятное отложит - до поры... Это - лучший из известных простых способов исследования мира :)

Классов в .NET - тысячи, так что исследования хватит надолго. Наша задача - только дать пищу для размышлений. Ну, например, в классе real мы увидим константы

real.PositiveInfinity; // бесконечность
real.NegativeInfinity; // минус бесконечность
real.NaN;              // не число
real.Epsilon;          // самое маленькое положительное вещественное 

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

Интересно еще поделить на ноль и извлечь корень из отрицательного числа:

r := r / 0;
writeln(r);
r := sqrt(-1);
writeln(r);

Дальнейшие исследования можно продолжить с типом DateTime. Для этого, правда, придется, подключить пространство имен System:

uses System;

DateTime.Now вернет текущие дату и время, их можно присвоить переменной типа DateTime, а потом вычленить из нее день, месяц, год, часы, минуты и секунды с помощью свойств Day, Month, Year, Hour, Minute, Second:

begin
  var d: DateTime := DateTime.Now;
  writeln(d.Day,'.',d.Month,'.',d.Year);
  writeln(d.Hour,':',d.Minute,':',d.Second);
end.

Как, вы еще не знаете, что такое пространства имен и свойства классов? О, да у вас еще все впереди!

Новости

30.08.17. Вышла версия 3.3. Новые модули Graph3D и GraphWPF

19.01.17. Добавлена операция безопасного среза: a?[-1:5:2]

29.08.16. Вышла версия 3.2. Реализован оператор yield.

12.02.16. Вышла версия 3.1. Добавлены кортежи в стиле (a,b) и кортежное присваивание (a,b) := (b,a)

Случайная программа

// Использование ассоциативного массива Dictionary<string,integer>
// Уровень сложности: 1

begin
  var d := new Dictionary<string,integer>;
  d['бегемот'] := 2;
  d['крокодил'] := d['бегемот'];
  d['крокодил'] += 1;
  d['жираф'] := 1;
  
  // Цикл по ассоциативному массиву
  foreach var k in d do
    writeln(k.Key:9, k.Value:3);
end.