В чём разница между конструктором и initialize методом в Ruby?

Я так понимаю, так как Ruby динамический, при создании объекта, необходимо ему присвоить поля для управления состоянием объекта и это происходит при помощи initialize. Для меня конструктор инициализирует переменные значениями.

А что если, у меня 2 метода initialize с разной сигнатурой и почему initialize нельзя называть конструктором объектов?

class A

	def initialize(param1, param2)
		@param1, @param2 = param1, param2
	end

	def initialize(param1)
		@param1 = param1
	end

	def m1
		puts @param2
	end

end

# Почему m1 не выводит ни ошибку, ничего
s = A.new ("val")
s.m1
  • Вопрос задан
  • 8279 просмотров
Решения вопроса 2
omun
@omun
1. Руби не поддерживает методы с разными сигнатурами. Но вместо ошибки он просто принимает последнюю вычисленную. В вашем случае первый метод init затрётся вторым. Для примера поменяйте их местами и вызов A.new(1) вернёт ошибку о недостаточности аргументов.
Корни этой проблемы тянутся из динамичности руби и отсутствия pattern matching.

2. initialize нельзя назвать конструктором, потому что конструктором фактически является метод класса new. И вот в A.new всегда вызывается метод инстанса initialize, если он присутствует. Но это настолько незначительное замечание, что можно и initialize называть конструктором, ошибка на данном этапе не существена.

По поводу нескольких конструкторов - вот вам шаблон:
def initialize(*args)
  if args.length == 1
    #initialize method 1
  else
    #initialize method 2
  end
end
Ответ написан
AMar4enko
@AMar4enko
Называйте как хотите, это не принципиально.
По поводу двух initialize - есть такое понятие ruby way.
Так вот, ruby way это что-то вроде
class A
    def initialize(params)
        self.class.class_eval {attr_accessor *params.keys}
        params.each {|key,value| send("#{key}=",value)}
    end    
end    

val = A.new(:param1 => 'test', :param2 => 'test2')


Для того, что бы иметь возможность инициализировать объекты по разным сценариям, вы можете использовать статические методы, возвращающие должным образом инициализированные объекты, например:
class A
    class << self
        def with_param(param1) self.new(:param1 => param1); end    
        def with_two_params(param1,param2) self.new(:param1 => param1, :param2 => param2);  end    
    end        
    def initialize(params)
        self.class.class_eval {attr_accessor *params.keys}
        params.each {|key,value| send("#{key}=",value)}
    end    
end    

p A.with_param('test')

p A.with_two_params('test1','test2')
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы