【问题标题】:Can I tell a Ruby method to expect a specific parameter type?我可以告诉 Ruby 方法期望特定的参数类型吗?
【发布时间】:2013-01-12 14:11:11
【问题描述】:
def doSomething(value)
    if (value.is_a?(Integer))
        print value * 2
    else
        print "Error: Expected integer value"
        exit
    end
end

我可以告诉 Ruby 方法某个参数应该是整数,否则会崩溃?像 Java。

【问题讨论】:

标签: ruby methods parameters


【解决方案1】:

不,你不能。你只能做你已经在做的事情:自己检查类型。

【讨论】:

  • @Omega 一般来说,没有理由将自己限制在某些类型上。如果给定类型支持您尝试对其执行的操作(在这种情况下:如果它可以乘以 2),则将方法限制为仅一种类型会降低其灵活性(例如:为什么用户不应该能够使用您的方法将浮点值或复数加倍吗?)。如果该类型不支持该操作,无论如何都会报错。​​
  • 我认为如果 Ruby 有这个特性,当你用一个好的 IDE 编写一个 Ruby 程序时,IDE 将能够“警告你”说“等等,你即将将不受支持的值传递给此方法,您将遇到麻烦”,就像使用 Java 大声笑一样。但除此之外,是的,你是对的,无论如何我都会收到错误 XD。
  • 顺便问一下,如果是这样的话,Java是不是有“缺陷”?还是我在谈论两个完全不同的世界,我根本不应该比较?
  • @Omega Java 非常不同,Java 中的类型错误是编译时错误,而不是运行时错误。因此,在 Java 中,当给定整数以外的值时,该方法不会崩溃——它一开始就不会编译。这称为静态类型。 Ruby 不是静态类型的有很多原因——包括简洁性和灵活性。向 Ruby 添加类型注释和添加静态类型将是两双不同的鞋子。静态类型无法与 Ruby 的某些特性(比如能够在运行时定义方法)结合使用。
  • @sepp2k 方法接受多种类型的情况非常罕见,在大多数情况下,方法依赖于确切的类型或接口。当代码增长时,没有类型实际上有点痛苦,你不知道类型方法需要什么,并且每次都需要查看文档,如果文档不存在,那么甚至查看代码只是为了弄清楚什么类型方法需要。
【解决方案2】:

我迟到了,但我想补充一点:

Ruby 中一个非常重要的概念是Duck Typing。这个原则背后的想法是,你并不真正关心变量的类型,只要它们可以做你想做的事情。您在方法中想要的是接受一个响应 (*) 的变量。只要实例可以相乘,您就不必关心类名。

因此,在 Ruby 中,#responds_to? 方法比 #is_a? 更常见

一般来说,只有在接受来自外部来源的值(例如用户输入)时,您才会进行类型断言。

【讨论】:

    【解决方案3】:

    我建议加薪,除非方法开头的类型匹配

    def do_something(value)
      raise TypeError, 'do_something expects an integer' unless value.kind_of?(Integer)
      ...
    end
    

    这会引发错误并退出,除非值为 Integer

    【讨论】:

      【解决方案4】:

      如果您认为有必要,您可以随时提出异常。

      def doSomething(value)
          if (value.is_a?(Integer))
              print value * 2
          else
              raise "Expected integer value"
          end
      end
      

      您是否真的想要这样做是一个单独的问题。 :)

      【讨论】:

      • 你可以像这样让它更干净: def doSomething(value);提高“预期的整数值”,除非 value.is_a?整数;打印值*2;结束
      • 我相信提出ArgumentError会比简单的RuntimeError更精确。
      • 你能想象对每个方法的每个参数都这样做吗?
      【解决方案5】:

      Ruby 没有参数类型验证,但您可以为所有对象添加糖方法以方便验证类型,如下所示:

      def doSomething(value)
         print value.should_be(Numeric) * 2
      end
      

      def initialize(fruit)
         @fruit = fruit.should_be(Fruit)
      end
      
      Object.class_eval do
      
        def should_be cls
          hide_from_stack = true
          if self && !self.is_a?(cls)
            raise("Expected class #{cls}, got #{self.class}")
          end
          self
        end
      
      end
      

      【讨论】:

      • 也可以使用RBS为Ruby方法添加类型签名。
      猜你喜欢
      • 1970-01-01
      • 2011-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-04
      • 2017-07-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多