Определение приватных классов, констант и методов класса в 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