【问题标题】:ruby parameters returning themselvesruby 参数返回自己
【发布时间】:2016-10-24 17:43:07
【问题描述】:

我在 Windows 10 x64 上运行 Ruby 2.3.1 x64。

我的代码:

class Credentials

  attr_reader :username, :password

    def initialize(username = nil, password = nil)
        @username = username
        @password = password
        get_credentials if !@username || !@password #Gets credentials if none are specified
    end

  def get_credentials
    @username = ask("Username:  ") { |q| q.echo = true }
    @password = ask("Password:  ") { |q| q.echo = "*" }
  end

end

忽略 get_credentials 的古怪之处,它是一个名为 Highline 的 gem,出于安全原因,我使用它来隐藏输入。

当我执行以下操作时:

$user = Credentials.new(username: "foo", password: "bar")

我得到这个回报:

#<Credentials:0x000000038ecf30 @password=nil, @username={:username=>"foo", :password=>"bar"}>

同样,调用 $user.username 会返回以下内容:

{:username=>"foo", :password=>"bar"}

什么时候应该返回: “富”

调用 $user.password 返回 nil。

谁能以亨利·汉密尔顿的名义告诉我为什么会发生这种情况?!我已经多次使用散列参数,它总是工作得很好。为什么要把每个参数设置都塞进一个参数中?

【问题讨论】:

  • 搞砸了,暂时放了这个标题,以为我会修复它,然后忘记了,现在我不能改变它......

标签: ruby object parameter-passing ruby-2.3


【解决方案1】:
$user = Credentials.new(username: "foo", password: "bar")

您只向初始化方法传递了一个参数,即散列。用户名属性的哈希值和密码属性的 nil。试试

$user = Credentials.new("foo", "bar")

或者,如果你真的想要关键字参数,那么

def initialize(username: nil, password: nil)

【讨论】:

    【解决方案2】:

    当您定义一个方法/构造函数时,您不会像任何其他编程语言一样按名称传递参数,而是按值传递参数,所以:

    $user=Credentials.new("foo","bar")
    

    会做你想做的。

    这是几乎所有编程语言的默认设置,您的问题应该是“这是如何工作的”,因为 ruby​​ 是动态类型的,语法 key1: val1,key2: val2,... 是新的哈希语法(从 ruby​​ 1.9 开始),a哈希是一个键值数据结构,所以你的:

    $user=Credentials.new(username: 'foo',password: 'bar')
    

    实际上只使用一个参数调用构造函数,该参数是用户名,其值为{username: 'foo',password: 'bar'},并且因为初始化是使用默认参数定义的,所以password 的值为nil

    现在,如果您确实想按名称传递参数,则必须像这样定义构造函数:

    def initialize(username: nil,password: nil)
    //code
    end
    

    之后你可以这样做:

    $user=Credentials.new(username: 'foo',password: 'bar')
    

    并期望它表现得如你所愿。

    请注意,在 ruby​​ 2 中引入了关键字参数(即通过名称传递参数),还请注意,您可以使用接受一个参数的构造函数来实现相同的效果,该参数是这样的散列:

    def initialize(params={})
    //code
    end
    

    但是这种方式不限制参数的数量和名称(你可以调用Credentials.new(fooprop: 'foovalue') 并且不会抛出错误),它还需要对代码进行一些更改。

    在某些编程语言中可以找到关键字参数功能,当函数有很多参数或让程序员清楚参数的用途时,它很有用。

    【讨论】:

    • 谢谢!对于任何 Google 路人来说,我的代码的问题是使用(用户名 = nil,密码 = nil)而不是(用户名:nil,密码:nil)。这是标准默认参数的语法,而不是哈希。因此,当我使用 Credentials.new() 实例化对象并为参数指定散列时,实际上只是将该散列存储在第一个参数变量中。
    • 为了进一步简化,如果其他人遇到这个问题,只需将 'def foobar(foo = nil, bar = nil)' 更改为 'def foobar(foo: nil, bar: nil)'。正是这种语法差异告诉方法它是否将使用标准顺序参数或哈希作为输入。
    【解决方案3】:
    def initialize(params={})
        @username = params[:username]
        @password = params[:password]
        @username || @password || get_credentials #simply
    end
    

    然后:

    $user = Credentials.new(username: "foo", password: "bar")
    

    【讨论】:

    • 这个答案不限制参数的数量和名称
    猜你喜欢
    • 2018-08-19
    • 2021-05-15
    • 2016-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-06
    • 2019-04-02
    相关资源
    最近更新 更多