Блог

Ruby: Класс

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

Класс

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

Определяем класс
Классы в Ruby это уникальные объекты – каждый из которых является экземпляром класса class. Определяется с помощью ключевого слова class, за которым следует end.

class Hello
    def initialize(name)
        @name = name
    end

    def say
        p "Hello, "+ @name
    end
end

hi = Hello.new('M')
hi.say

Метод initialize относится к соглашениям языка и действует подобно конструктору классов в других языках. Метод является первым кодом, который выполняется после того, как создан объект.

Класс сам по себе является объектом, даже если вы непосредственно не создавали его. Классы всегда открыты, поэтому вы можете дополнять любой класс, даже встроенные классы, такие как String/Array.

class Array
  def range_to(n = 10)
    (1..n).to_a
  end
end

p [].range_to 5 #=> [1, 2, 3, 4, 5]

Переменные экземпляра
Это переменная, которая доступна изнутри экземпляра класса и ограничена областью видимости, потому что принадлежит объекту. Переменная экземпляра начинается с символа “коммерческое at”(@).  Можно определять переменную экземпляра внутри метода. Можно получить доступ снаружи объекта через метод.

class Hello
    @user = 'TEST'
end

Чтобы извлечь значение, вы должны определить метод.

class Hello

  def user
    @user = 'TEST'
  end

end

h = Hello.new
p h.user

Метод user относится к тому виду методов, которые называют метод-аксессор (accessor – средство доступа) или геттер (getter). Он получает значение переменной из экземпляра класса. Еще существует сеттер (settert), который устанавливает значение переменной.

class Hello

  def user
    @user
  end

  def user=(value)
    @user = value
  end

end

h = Hello.new
p h.user
h.user=('Timmi')
p h.user

=>nil
=>"Timmi"

 

Аксессоры
Ruby упрощает создание геттеров и сеттеров с помщью метапрограммирования attr, attr_reader, attr_writer и attr_accessor из класса Module. Метапрограммирование — это вид программирования, связанный с созданием программ, которые порождают другие программы как результат своей работы (в частности, на стадии компиляции их исходного кода), либо программ, которые меняют себя во время выполнения (самомодифицирующийся код).
Метод attr создает метод-геттер, именем которого является символ и необязательный метод-сеттер (если второй параметр равен true).

class Hello
  attr :user, true
end

p Hello.instance_methods - Object.instance_methods

h = Hello.new
h.user = '%username%'
p h.user

Result:
> ["user", "user="]
> "%username%"

При вызове attr с параметром :user и true класс Hello будет обладать методами user/user=.

Метод attr_reader автоматически создает одну или несколько переменных экзамляра с соответствующими методами, которые возвращают значения.

Метод attr_writer автоматически создает одну или несколько переменных экземпляра с соответствующими методами, которые устанавливают значение.

class Hello
  attr_reader :user
  attr_writer :user
end

h = Hello.new
h.user = '%username%'
p h.user
p h.instance_variables.sort

p Hello.instance_methods - Object.instance_methods

Метод attr_accessor выполняет для одного или более методов экземпляра класса ту же самую работу, что и attr_reader/attr_writer

class Hello
  attr_accessor :user, :about, :gender
end

p Hello.instance_methods - Object.instance_methods

Result:
> ["user", "user=", "about", "about=", "gender", "gender="]

Переменные класса
В Ruby имя переменной класс начинается двумя “коммерческими at”  (@@)/
Нужно проинициализировать атрибут класса перед использованием.

class Hello
  @@user = '%username%'

  def initializ(name)
    @name = name
  end

  def say
    @@user = @name

    return "Hello, "+ @@user.to_s
  end

  def bye
    return "Bye "+ @@user.to_s
  end

end

h = Hello.new
p h.say
p h.bye

Методы класса

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

class Area
  def Area.rect(len, width, units = 'inches')
    area = len * width
    printf("Tha area of this rectangle is %.2f %s.", area, units)
    sprintf("%.2f", area)
  end
end

Area.rect(12.5, 16)

Одноэлементые классы 
Можно также определить метод класса путем использования класса внутри класса – одноэлементного класса.

class Area
   class << self
      def rect(len, width, units = 'inches')
         area = len * width
         printf("Tha area of this rectangle is %.2f %s.", area, units)
         sprintf("%.2f", area)
      end
   end
end

Area.rect(7, 10)
p Area.instance_methods - Object.instance_methods

> Tha area of this rectangle is 70.00 inches.
> []

Определение метода одноэлементного класса – далее приведен метод, связан с объектом

class Hello
end

h = Hello.new
def h.say
  puts "Hello, from say"
end

h.say
p Hello.instance_methods - Object.instance_methods

Result:
> Hello, from say
> []

Наследование

В Ruby поддерживается одиночное наследование, что означает, что класс может наследоваться только от одного класс – родительского или супер класса. После наследования дочерний класс становится наследником и получает доступ к методам. За наследование отвечает оператор меньше (<).

class Name
  attr_accessor :first_name, :last_name
end

class Address < Name
  attr_accessor :street, :city, :country
end

a = Address.new
puts a.respond_to?(:first_name)

Модули

дополнительно к классам в Ruby существуют еще модули. Модули подобны классу, но для него нельзя создать экземпляр, как для класс. Класс может вкл. модуль, когда создается экземпляр, он получает собственность вкл. модуля. Методы из модуля становятся методами класса, который вкл. модуль. Это называется смешиванием, а на модуль ссылаются как на mixin.

Модуль в Ruby является формой пространства имен. Пространство имен – это множество имен, таких как имена методов, которые имеют область видимости и контекст. Модуль связывает одно имя с набором имен методов и костант.

module Dice

  def roll
    r_1 = rand(2)
    r_2 = rand(6)

    r1 = r_1>0?r_1:1
    r2 = r_2>0?r_2:6

    total = r1+r2

    printf("You rolled %d and %d (%d).\n", r1, r2, total)
    total
  end

end

class Game
  include Dice
end

g = Game.new
g.roll

Result:
You rolled 1 and 3 (4).

Если модуль в отдельном файле, вам нужно так же как и с классом подключить через require файл.
Присоединить префикс к методу модуля и затем вызвать этот метод.

module Binary

  def Binary.to_bin(num)
    bin = sprintf("%08b", num)
  end

end

p Binary.to_bin(2)

Методы public, private и protected

Видимость или тип доступа методов и констант может быть установлен при помощи методов public, private и protected.
public – доступен все и отовсюду
private – получателем является текущий объект или self, область видимости текущий объект
protected – может использоваться только экземплярами класса, в котором он был определен или порожденными классами.

class Names

  def initialize(first, second, nick, pet)
    @first = first
    @second = second
    @nick = nick
    @pet = pet
  end

  # public
  def first
    @first
  end

  def second
    @second
  end

  # все нижеследующие методы имеют тип доступа private
  # пока не будут изменены
  private
  def nick
    @nick
  end

  # будет protected пока не измените на public/private
  protected
  def pet
    @pet
  end

end

n = Names.new('Test', 'User', '%username%', 'Husky')
p n.first
p n.second

p n.nick
p n.pet


Ссылки
http://ruby-doc.org/
http://www.ruby-lang.org/en/documentation/quickstart/
http://www.ruby-lang.org/en/documentation/quickstart/
http://www.tutorialspoint.com/ruby/ruby_loops.htm
http://habrahabr.ru/post/71878/
Ruby/Справочник/Class
Ruby/Справочник/Module

Книга:
Майкл Фитцджеральд – Изучаем Ruby: 2008