Cайт веб-разработчика, программиста Ruby on Rails ESV Corp. Екатеринбург, Москва, Санкт-Петербург, Новосибирск, Первоуральск

Определение приватных классов, констант и методов класса в Ruby

Для определения приватных (private) классов, констант и методов класса в Ruby предусмотрены методы класса private_constant и private_class_method, соответственно. Естественно, нельзя обойти стороной механизм class << self - eigenclass синглтон-класс (обособленный, персональный, собственный класс), используя private в определении метода.

При этом приватный класс или константа доступны в методах экземпляра (объекта) класса, но не приватные методы класса. Использование приватных классов, например, очень хорошо подойдёт для контролируемого создания экземляров класса.

class Test

  # === константы

  OPEN_CONSTANT = 'open'

  # приватная константа
  TEST = [1,2,3]
  private_constant :TEST

  # === методы класса

  # приватный метод класса
  # либо доступно более краткое определение:
  # private_class_method def self.private_print
  def self.private_print
    puts "private_print: #{TEST.inspect}"
  end
  private_class_method :private_print

  # общедоступный метод класса
  def self.class_test_print

    # доступ к константе
    puts "class test: #{TEST.inspect}"

    # вызов приватного метода класса из 
    # общедоступного метода класса
    private_print

  end

  # === методы экземпляра (объекта) класса

  def test_print
    puts "instance test: #{TEST.inspect}"
  end

  def test_private
     # попытка вызова приватного метода класса напрямую
    self.class.private_print
  end

  def test_class_private
    # вызов общедоступного метода класса, внутри которого 
    # производится вызов приватного метода класса
    self.class.class_test_print
  end

  # === приватный класс

  class Inner
    def hello = puts 'hello'
  end
  private_constant :Inner

  # получить экземляр приватного класса
  def self.get_inner = Inner::new
  def instance_get_inner = Inner::new

  # === синглтон-класс

  # доступ к классу, как к объекту: Test - это объект класса Class
  # все определения внутри относятся к синглтон-классу
  class << self

    # константа доступна через
    # Test::singleton_class::S
    S = 'singleton const'

    # метод класса, используем обычный стиль объявления private
    # равносильно def self.private_singleton
    private def private_singleton
      puts 'singleton'
    end

  end

end

# === тесты

p Test::OPEN_CONSTANT      # => "open"
p Test::TEST               # => private constant Test::TEST referenced (NameError)
p Test::S                  # => uninitialized constant Test::S (NameError)
p Test::singleton_class::S # => "singleton const"

Test::private_print     # => private method 'private_print' called for class Test (NoMethodError)
Test::private_singleton # => private method 'private_singleton' called for class Test (NoMethodError)
Test::class_test_print  # => class test: [1, 2, 3]
                        #    private_print: [1, 2, 3]
t = Test::new
t.test_print            # => instance test: [1, 2, 3]
t.test_private          # => private method 'private_print' called for class Test (NoMethodError)
t.test_class_private    # => class test: [1, 2, 3]
                        #    private_print: [1, 2, 3]

ti = Test::Inner::new   # private constant Test::Inner referenced (NameError)
ti = Test::get_inner
ti.hello                # => hello
ti2 = t.instance_get_inner
ti2.hello               # => hello