Классы и объекты — различия между версиями
Root (обсуждение | вклад) м (→Конструкторы) |
Root (обсуждение | вклад) м (→Поля) |
||
Строка 189: | Строка 189: | ||
Примеры: | Примеры: | ||
<source lang="kpp"> | <source lang="kpp"> | ||
− | + | var int m_x; | |
− | + | const m_y = 0; | |
− | + | var m_stream = new stream; | |
</source> | </source> | ||
Версия 20:59, 7 сентября 2007
Содержание |
Основой всей платформы Gide является объектно-ориентированный принцип. Для виртуальной машины Gide не существует понятия целого числа, строки или массива. Все, чем она оперирует - это объекты.
Язык K++ в полной мере использует тот же самый принцип. Для него нет отличия между типом int (целое число) и MyWeirdClass (какой-то класс, определенный пользователем): везде, где можно использовать int, можно использовать MyWeirdClass и наоборот. Например, ничто не мешает унаследовать свой класс от класса int, равно как ничто не мешает определить математические операторы для класса MyWeirdClass и использовать объекты этого класса в арифметических выражениях.
Понятие класса
Под классом понимается некоторая абстрактная сущность, задающая поведение объектов. Класс представляет собой набор следующих элементов:
- полей, т.е. объектов, которые используют объекты данного класса;
- методов, т.е. функций, определяющих поведение данного объекта;
- свойств, определяющих взаимодействие других объектов с объектами данного класса.
Класс может иметь одного или нескольких родителей; об этом подробнее см. ниже.
Все поля, методы и свойства класса могут находиться в различных областях видимости:
- private - видимость только внутри методов данного класса;
- protected - видимость внутри методов данного класса и его дочерних классов;
- public - видимость для всех.
Вот пример объявления класса:
<source lang="kpp"> class MyWeirdClass {
var m_x = 0; // поле m_x, изначально проинициализированное нулем const m_y = 1; // поле m_y, которое нельзя изменять
// методы класса public const function int get_mul() { return m_x * m_y; } public function void set_mul(int x) { m_x = x / m_y; }
// свойство класса public property mul read get_mul write set_mul;
} </source>
Понятие объекта
Под объектом подразумевается экземпляр того или иного класса, т.е. сущность, поведение которой задается соответствующим классом.
Для создания объекта того или иного класса служит оператор new: <source lang="kpp">
var myWeirdObject = new MyWeirdClass;
</source>
Наследование
Под наследованием классов понимается создание класса, расширяющего функционал одного или нескольких классов (родителей).
Наследование гарантирует, что к дочерним классам применимы все операции, доступные в родительском классе. Таким образом, любой алгоритм, работающий с объектами родительского класса, может работать с объектами его дочерних классов.
Для задания наследования, в объявлении класса следует указать ключевое слово extends и следующий за ним список родительских классов, разделенный запятыми.
Вот пример кода:
<source lang="kpp"> class Box // коробка {
// из чего сделана коробка? public const function string material() { return "Картон"; }
// что в коробке? public const function string contents() { return "Пусто"; }
}
class BoxWithPotatoes extends Box // коробка с картошкой {
public const function string contents() { return "Картошка"; }
}
function OutputBox(const Box b) {
STDOUT.print("Материал: " + b.material() + ", содержит: " + b.contents() + "\n");
}
function main() {
var b1 = new Box; var b2 = new BoxWithPotatoes; OutputBox(b1); // Материал: Картон, содержит: Пусто OutputBox(b2); // Материал: Картон, содержит: Картошка
} </source>
- Замечание о множественном наследовании
- Существует одно ограничение при использовании множественного наследования: его нельзя применять для наследования от классов стандартной библиотеки. Это ограничение связано с архитектурой платформы Gide.
Методы
Метод - это некоторая функция, управляющая поведением объекта данного класса.
При объявлении метода могут быть указаны следующие ключевые слова, в указанном порядке:
- private, protected или public
- определяет область видимости метода;
- static
- метод является статическим, см. ниже;
- const
- метод не изменяет объект;
- function или constructor
- о конструкторах см. ниже;
- const
- метод возвращает результат, который нельзя изменять;
После этого идет тип, возвращаемый методом. Если он опущен - возвращается динамическая переменная; если вместо типа указано ключевое слово void - метод не возвращает результата.
За типом идет имя метода, затем - перечисление аргументов в скобках. Подробнее об этом можно прочитать в разделе Функции.
Тело метода может быть объявлено как непосредственно в теле класса, так и вынесено за его пределы. Например:
<source lang="kpp"> class MyClass {
public const function string F1() { return "smth"; } public const function string F2();
};
function string MyClass::F2() {
return F1();
} </source>
При вынесении функции за пределы класса, в заголовке вынесенной функции необходимо указать тип возвращаемого результата и параметры функции; все остальные ключевые слова указывать не обязательно.
В теле метода доступны все поля, методы и свойства данного класса и его предков. Например, в коде, приведенном выше, метод F2 вызывает метод F1 для того же объекта.
Статические методы
Статический метод класса - это метод, относящиеся к данному классу, но не объекту этого класса. Т.е. это некоторая вспомогательная для данного класса функция.
При объявлении статического метода нужно указать ключевое слово static.
В теле статического метода нет возможности напрямую обращаться к другим методам данного класса, т.к. статическому методу недоступен объект класса. Фактически, единственным отличием статического метода от обычной функции является то, что такой метод может обращаться к защищенным полям и методам класса.
Пример: <source lang="kpp"> class MyClass {
public static function string Info() { return "Я MyClass!"; }
};
function f() {
// Вызов статического метода: var myClassInfo = MyClass.Info();
} </source>
Конструкторы
Конструктор класса - это метод, инициализирующий объект класса.
С точки зрения языка, конструктор - это статический метод класса, возвращающий экземпляр данного класса.
Таким образом, следующие объявления в рамках класса MyClass эквивалентны: <source lang="kpp"> public constructor Create(); public static MyClass Create(); </source>
Тело конструктора чаще всего выглядит следующим образом: сначала создается экземпляр класса при помощи оператора new, затем производятся некоторые действия, инициализующие этот объект, и, наконец, этот объект возвращается в качестве результата: <source lang="kpp"> class MyClass {
var int m_X; public constructor Create(const int x = 0) { var self = new MyClass; self.m_X = x; return self; }
}
function f() {
var myObj = MyClass.Create(7);
} </source>
Поля
Поле класса - это некоторый объект, используемый объектом данного класса.
Объявление поля начинается с одного из трех ключевых слов:
- var
- объявление "обычного" поля;
- const
- данное поле является константой и не может быть изменено;
- mutable
- значение данного поля не влияет на состояние объекта, и его можно менять даже в методах, объявленных константными.
За ключевым словом следует тип поля и его имя; тип может быть опущен.
После имени может стоять знак "=" и выражение, инициализирующее значение данного поля.
Примеры: <source lang="kpp"> var int m_x; const m_y = 0; var m_stream = new stream; </source>
Тип поля определяется по следующим правилам:
- если тип указан явно, ничего определять не надо;
- если тип не указан, но при объявлении использован инициализатор - типом становится тип результата инициализатора;
- в противном случае, для поля устанавливается динамический тип.
Важное замечание: В K++ доступ к полям имеет только объект класса - т.е. фактически все поля находятся в закрытой (private) области видимости. Для предоставления доступа к полям следует использовать свойства (см. ниже).