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

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

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

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

end

# === тесты

p Test::OPEN_CONSTANT   # => "open"
p Test::TEST            # => private constant Test::TEST referenced (NameError)
Test::private_print     # => private method 'private_print' 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