11.1.4. Создание атрибутов и методов уровня класса

11.1.4. Создание атрибутов и методов уровня класса

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

Мы можем определять собственные методы класса, как показано в разделе 11.1.1. Конечно, их функциональность не ограничивается конструированием — они могут выполнять любые операции, имеющие смысл именно на уровне класса.

В следующем далеко не полном фрагменте предполагается, что мы создаем класс для проигрывания звуковых файлов. Метод play естественно реализовать как метод экземпляра, ведь можно создать много объектов, каждый из которых будет проигрывать свой файл. Но у метода detect_hardware контекст более широкий; в зависимости от реализации может оказаться, что создавать какие-либо объекты вообще не имеет смысла, если этот метод возвращает ошибку. Следовательно, его контекст — вся среда воспроизведения звука, а не конкретный звуковой файл.

class SoundPlayer

 MAX_SAMPLE = 192

 def SoundPlayer.detect_hardware

  # ...

 end

 def play

  # ...

 end

end

Есть еще один способ объявить этот метод класса. В следующем фрагменте делается практически то же самое:

class SoundPlayer

MAX_SAMPLE =192

 def play

  # ...

 end

end

def SoundPlayer.detect_hardware

 # ...

end

Единственная разница касается использования объявленных в классе констант. Если метод класса объявлен вне объявления самого класса, то эти константы оказываются вне области видимости. Например, в первом фрагменте метод detect_hardware может напрямую обращаться к константе MAX_SAMPLE, а во втором придется пользоваться нотацией SoundPlayer::MAX_SAMPLE.

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

Традиционный пример использования переменных класса - подсчет числа его экземпляров. Но они могут применяться всегда, когда информации имеет смысл в контексте класса в целом, а не отдельного объекта. Другой пример приведен в листинге 11.3.

Листинг 11.3. Переменные и методы класса

class Metal

 @@current_temp = 70

 attr_accessor :atomic_number

 def Metal.current_temp=(x)

  @@current_temp = x

 end

 def Metal.current_temp

  @@current_temp

 end

 def liquid?

  @@current_temp >= @melting

 end

 def initialize(atnum, melt)

  @atomic_number = atnum

  @melting = melt

 end

end

aluminum = Metal.new(13, 1236)

copper = Metal.new(29, 1982)

gold = Metal.new(79, 1948)

Metal.current_temp = 1600

puts aluminum.liquid? # true

puts copper.liquid?   # false

puts gold.liquid?     # false

Metal.current_temp = 2100

puts aluminum.liquid? # true

puts copper.liquid?   # true

puts gold.liquid?     # true

Здесь переменная класса инициализируется до того, как впервые используется в методе класса. Отметим также, что мы можем обратиться к переменной класса из метода экземпляра, но обратиться к переменной экземпляра из метода класса нельзя. Немного подумав, вы поймете, что так и должно быть.

А если попытаться, что произойдет? Что если мы попробуем напечатать атрибут @atomic_number из метода Metal.current_temp? Обнаружится, что переменная вроде бы существует — никакой ошибки не возникает, — но имеет значение nil. В чем дело?

В том, что на самом деле мы обращаемся вовсе не к переменной экземпляра класса Metal, а к переменной экземпляра класса Class. (Напомним, что в Ruby Class — это класс!)

Мы столкнулись с переменной экземпляра класса (термин заимствован из языка Smalltalk). Дополнительные замечания на эту тему приводятся в разделе 11.2.4.

В листинге 11.4 иллюстрируются все аспекты этой ситуации.

Листинг 11.4. Данные класса и экземпляра

class MyClass

 SOME_CONST = "alpha"     # Константа уровня класса.

 @@var = "beta"           # Переменная класса.

 @var = "gamma"           # Переменная экземпляра класса.

 def initialize

  @var = "delta"          # Переменная экземпляра.

 end

 def mymethod

  puts SOME_CONST         # (Константа класса.)

  puts @@var              # (Переменная класса.)

  puts @var               # (Переменная экземпляра.)

 end

 def MyClass.classmeth1

  puts SOME_CONST         # (Константа класса.)

  puts @@var              # (Переменная класса.)

  puts @var               # (Переменная экземпляра класса.)

 end

end

def MyClass.classmeth2

 puts MyClass::SOME_CONST # (Константа класса.)

 # puts @@var             # Ошибка: вне области видимости.

 puts @var                # (Переменная экземпляра класса.)

end

myobj = MyClass.new

MyClass.classmeth1        # alpha, beta, gamma

MyClass.classmeth2        # alpha, gamma

myobj.mymethod            # alpha, beta, delta

Следует еще сказать, что метод класса можно сделать закрытым, воспользовавшись методом private_class_method. Это аналог метода private на уровне экземпляра. См. также раздел 11.2.10.

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Создание обобщенных методов

Из книги Язык программирования С# 2005 и платформа .NET 2.0. [3-е издание] автора Троелсен Эндрю

Создание обобщенных методов Чтобы научиться интегрировать обобщения в проекты, мы начнем с простого примера обычной подпрограммы свопинга. Целью этого примера является построение метода обмена, который сможет работать c любыми типами данных (характеризуемыми


Создание пользовательских атрибутов

Из книги Обработка баз данных на Visual Basic®.NET автора Мак-Манус Джеффри П

Создание пользовательских атрибутов Первым шагом процесса построения пользовательского атрибута является создание нового класса, производного от System.Attribute. В продолжение автомобильной темы, используемой в этой книге, мы создадим новую библиотеку классов C# с именем


Переопределение методов базового класса

Из книги Программирование на языке Ruby [Идеология языка, теория и практика применения] автора Фултон Хэл

Переопределение методов базового класса В порожденном классе можно определить методы и элементы данных с именами, которые уже используются в базовом классе. Соответствующие методы и элементы данных базового класса оказываются скрыты. Чтобы обратиться к ним, необходимо


Редактирование методов класса

Из книги Моделирование бизнес-процессов с BPwin 4.0 автора Маклаков Сергей Владимирович

Редактирование методов класса Выберите из списка элементов класса интересующий вас метод и нажмите правую кнопку мыши. На экране появится временное меню, показанное нами на рисунке 2.18. Это меню позволяет перейти к редактированию объявления или определения метода,


11.1.2. Создание атрибутов экземпляра

Из книги XSLT автора Хольцнер Стивен

11.1.2. Создание атрибутов экземпляра Имени атрибута экземпляра в Ruby всегда предшествует знак @. Это обычная переменная в том смысле, что она начинает существовать после первого присваивания.В ОО-языках часто создаются методы для доступа к атрибутам, чтобы обеспечить


11.2.10. Автоматическое определение методов чтения и установки на уровне класса

Из книги Технология XSLT автора Валиков Алексей Николаевич

11.2.10. Автоматическое определение методов чтения и установки на уровне класса Мы уже рассматривали методы attr_reader, attr_writer и attr_accessor, которые немного упрощают определение методов чтения и установки атрибутов экземпляра. А как быть с атрибутами уровня класса?В Ruby нет


3.3. Создание сущностей и атрибутов BPwin и их экспорт в ERwin

Из книги VBA для чайников автора Каммингс Стив

3.3. Создание сущностей и атрибутов BPwin и их экспорт в ERwin Если в процессе связывания стрелок с объектами модели данных окажется, что каких-либо сущностей или атрибутов не хватает, их можно добавить прямо в BPwin, а затем экспортировать в ERwin.Для редактирования сущностей


Элемент : создание новых атрибутов

Из книги C++. Сборник рецептов автора Диггинс Кристофер

Элемент <xsl:attribute>: создание новых атрибутов Аналогично тому, как вы можете создавать новые элементы при помощи <xsl:element> и устанавливать имя и содержимое элемента на этапе выполнения, при помощи элемента <xsl:attribute> это можно делать для атрибутов. У элемента два


Создание содержимого уровня блока:

Из книги автора

Создание содержимого уровня блока: <fo:block> Блоки играют важную роль в XSL-FO: они применяются для создания прямоугольных областей вывода, отделенных от других областей вывода в документе. Форматирующий объект <fo:block> применяется для форматирования таких элементов, как


Создание методов

Из книги автора

Создание методов Методы представляют собой обычные процедуры типов Sub и Function, которым выпало разместиться в модуле класса. Конечно, в большинстве случаев метод должен делать нечто, напрямую связанное с самим объектом, преобразуя данные, хранимые объектом. Но, при желании,


Создание собственных методов DrawPie и FillPie

Из книги автора

Создание собственных методов DrawPie и FillPie В данный момент .NET Compact Framework не поддерживает графические методы DrawPiе и FillPie, которые позволяли бы рисовать круговые секторы. Но можно создать свою версию этих методов, используя математические вычисления, как показано в листинге