Как я могу иметь более одного конструктора в ruby? - PullRequest
0 голосов
/ 13 октября 2019

Я хочу иметь более одного конструктора в Ruby. Я знаю, что должен использовать собственные методы, но дело в том, что я не знаю, как их реализовать. Например:

def initialize(n1 = 0,n2 = 0,n3 = 0)
  @num1 = n1
  @num2 = n2
  @num3 = n3
end

def self.MyClass(num1, num3)
...
end

def self.MyClass(num2,num3)
 ...
end

Итак, в первом случае я хочу дать значение только num1 и num3, а не num2. А во втором случае я хочу дать значение только для num2 и num3, но не для num1. Как я могу это сделать?

Ответы [ 3 ]

1 голос
/ 13 октября 2019

Не удалось достичь желаемого с помощью аргументов ключевого слова:

class MyClass
  attr_reader :num1, :num2, :num3
  def initialize(n1: nil, n2: nil, n3: nil)
    if n2.nil?
      puts 'num2 is nil'
    end
    if n3.nil?
      puts 'num3 is nil'
    end
    @num1 = n1 || 0
    @num2 = n2 || 0
    @num3 = n3 || 0
  end
end

MyClass.new(n1: 1, n2: 3)
# num3 is nil
# => <MyClass:0x0... @num1=1, @num2=3, @num3=0>

MyClass.new(n1: 4, n3: 1)
# num2 is nil
# => <MyClass:0x0... @num1=4, @num2=0, @num3=1>

Аргументы ключевых слов доступны начиная с ruby ​​2.0. Google или посмотрите, например, здесь для получения дополнительной информации об аргументах ключевых слов.

Если вы хотите оставаться близким к синтаксису MyClass (), вы можете настроить его следующим образом:

class MyClass
  attr_reader :num1, :num2, :num3
  def initialize(n1 = 0, n2 = 0, n3 = 0)
    @num1 = n1
    @num2 = n2
    @num3 = n3
  end
  def self.call(n1: nil, n2: nil, n3: nil)
    if n2.nil?
      puts 'num2 is nil'
    end
    if n3.nil?
      puts 'num3 is nil'
    end
    new n1, n2, n3
  end
end

MyClass.(n1: 1, n2: 3)
# num3 is nil
# => <MyClass:0x0... @num1=1, @num2=3, @num3=nil>
MyClass.(n1: 4, n3: 1)
# num2 is nil
# => <MyClass:0x0... @num1=4, @num2=nil, @num3=1>

Обратите внимание на '.'после имени класса.

Еще одна альтернатива - использовать def self.[](...) вместо def self.call(...), а ваши вызовы использовать MyClass[...] (без точки после класса).

0 голосов
/ 14 октября 2019

Для динамического конструктора вашего класса, я думаю, вам также нужно динамически attr_accessor ваших переменных экземпляра.
Поскольку нам нужно знать, какие переменные экземпляра инициализируются, мы должны объявить attr_accessor внутри блока initialize.
Я уже проверил это, и оно работает хорошо, вы можете попробовать его здесь:

class MultipleConstructors
  def initialize(args={})
    args.each do |k,v|
      instance_variable_set("@#{k}", v)
      self.class.send(:attr_accessor, *args.keys)
    end
  end
end

А затем вы можете получить или установить любую переменную экземпляра после инициализатора конструктора.

m = MultipleConstructors.new(a: 1, c: 4)
m2 = MultipleConstructors.new(d: 'blah', e: 100)
m3 = MultipleConstructors.new(f: true)

или вы можете инициализировать любой конструктор, какой захотите ...
ref: https://apidock.com/ruby/Module/attr_accessor

0 голосов
/ 13 октября 2019

Семантика Ruby о конструкторах в стороне (и комментарии Йорга об этом, как обычно, точны), вы сказали, что хотите создать класс, в котором вы присваиваете значение различным атрибутам в разных экземплярах класса, а невсе они в любом конкретном случае.

Вам не нужно использовать «собственные методы» (Ruby называет их «методами класса») для этого, и вам определенно не требуется «более одного конструктора» для этого. Просто укажите значение по умолчанию nil для каждого из них. Очень похоже на то, что у вас уже есть:

def initialize(n1 = nil, n2 = nil, n3 = nil)
  @num1 = n1
  @num2 = n2
  @num3 = n3
end

Теперь, если вы не установите их при инициализации экземпляра, их значение будет nil, и если вам нужно, вы можете проверитьчто в твоих методах.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...