类使用* args和Case语句初始化

时间:2014-05-22 22:14:48

标签: ruby

假设我有一个名为Task的类。

class Task
    attr_accessor :task_name, :start, :end

    def initialize(*args)
        length = args.length
        case length
        when 0
            puts "Task Created."
        when 1
            @task_name = args[0]
            puts "Task Created."
        when 3
            @task_name = args[0]
            @start = args[1]
            @end = args[2]
            puts "Task Created."
        else
            puts "Incorrect input" 
        end
    end
end

我想问一些有关此实施的问题:

  • 这是否正确处理了所有可能的初始化参数,或者在case语句中是否存在弱点?
  • 如果我尝试使用两个参数创建对象,则预期输出将为“输入不正确”。即使我从未设置过它的任何属性,仍然会创建对象(对吗?)。如果发送了非法数量的参数,有没有办法阻止创建对象?

3 个答案:

答案 0 :(得分:1)

不要使用" new",使用另一种调用" new"如果参数有效

class Task
    attr_accessor :task_name, :start, :end
    def initialize(*args)
        @task_name = args[0]
        @start = args[1]
        @end = args[2]
        puts "Task Created."
    end
    def self.fabricate(*args)
        if [0, 1, 3].include?(args.length)
           return new(*args)
        else
           puts "incorrect input"
           return nil
        end
    end
end

result = Task.fabricate("job", 5, 7)

答案 1 :(得分:1)

您可以通过引发错误来阻止对象的创建,最常见的是ArgumentError。当参数写在方法签名中时我喜欢它,所以我会这样做:

def initialize(task_name = nil, start = nil, end = nil)
  unless [start, end].all?(&:nil?) || [start, end].none?(&:nil?)
    raise ArgumentError, 'provide both start and end or none'
  end

  @task_name = task_name
  @start = start
  @end = end
end

很酷的是,当您传递给许多参数时,您可以免费获得ArgumentError。 if条件也可以写得更短,因为它基本上是XOR。不过我认为这是不太可以理解的:

def initialize(task_name = nil, start = nil, end = nil)
  if start.nil? != end.nil?
    raise ArgumentError, 'provide both start and end or none'
  end

  @task_name = task_name
  @start = start
  @end = end
end

答案 2 :(得分:1)

要回答您的问题,您需要了解new方法的工作原理。如果它是用ruby编写的,它看起来像这样:

class Class
  def self.new(args*)
    object = allocate
    object.initialize(*args)
    object
  end
end

allocate方法负责在ruby的内存堆slab中创建一个新对象。分配对象时,将对此对象执行initialize方法,并返回对象本身。

那么如何防止新对象被退回? - 在initialize中提出异常!

您可以通过以下方式完成:

class Task
  attr_accessor :task_name, :start, :end

  def initialize(*args)
    raise ArgumentError, "wrong number of arguments (#{args.length} for 0,1 or 3" unless [0,1,3].include?(args.length)
    @task_name, @start, @end = args 
  end

end