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.

11.1.5. Наследование суперклассу

Можно унаследовать класс, воспользовавшись символом <:

class Boojum < Snark

 # ...

end

Это объявление говорит, что класс Boojum является подклассом класса Snark или — что то же самое — класс Snark является суперклассом класса Boojum. Всем известно, что каждый буюм является снарком, но не каждый снарк — буюм.

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

Попутно отметим, что во многих языках, например в C++, допускается множественное наследование (МН). В Ruby, как и в Java, и в некоторых других языках, множественного наследования нет, но наличие классов-примесей компенсирует его отсутствие (см. раздел 11.1.12).

Рассмотрим несколько более реалистичный пример. У нас есть класс Person (человек), а мы хотим создать производный от него класс Student (студент).

Определим класс Person следующим образом:

class Person

 attr_accessor :name, :age, :sex

 def initialize(name, age, sex)

  @name, @age, @sex = name, age, sex

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату