Ruby类

时间:2018-11-02 01:03:17

标签: ruby

这是一个伪造的银行应用程序:

class Bank
    private def initialize
        $login = Hash.new
        puts "Welcome to HEIDI BANK!"
    end

    def add(keyVal)
        keyVal.each do |key, value|
            $login[key] = value
        end
    end

    def NewUser
        puts "What is the name of the user you would like to add?"
        user = gets.chomp
        puts "What is the password you would add?"
        pass = gets.chomp
        passsym = pass.to_sym
        $login.add(user => passsym)
    end
end

you_bank = Bank.new
you_bank.NewUser

当我尝试运行它时,我得到:

Welcome to HEIDI BANK!
What is the name of the user you would like to add?
12
What is the password you would add?
13

然后引发错误:

in `NewUser': undefined method `add' for {}:Hash(NoMethodError)

如何解决此错误?看来我可能必须弄清楚如何调用Bank.add之类的东西。像数组中的add一样,哈希是否内置了samp_array.push函数?

2 个答案:

答案 0 :(得分:1)

您将add定义为Bank的实例方法,但是您正在$login上调用它,它是Hash的实例。在Bank本身的实例上调用它,可以省略:

def NewUser
  ...
  add(user => passsym)
end

答案 1 :(得分:1)

我已经在评论中提供了答案,但我想提供更长的答案以帮助您。您似乎是一个年轻的程序员,并且是Ruby的新手,所以我想帮助您养成健康的习惯。因此,我对您的代码进行了重构,并添加了注释,以解释更改,并带有指向资源的链接,您可以阅读这些链接以帮助了解更改原因。

这些大多是小问题,但是在编写任何类型的生产代码或编写将来其他人可能必须阅读或使用的代码时,它们都很重要。

# Allows the use of STDIN.noecho which will not echo text input back to the console:
# https://stackoverflow.com/a/29334534/3784008
require 'io/console'

# Use two spaces of indentation for Ruby, not tabs and not 4 spaces:
# https://github.com/rubocop-hq/ruby-style-guide#source-code-layout
class Bank
  # The initialize method is not a private method:
  # https://stackoverflow.com/q/1567400/3784008
  def initialize
    # Use single quotes for non-interpolated strings
    # https://github.com/rubocop-hq/ruby-style-guide#strings
    puts 'Welcome to HEIDI BANK!'

    # Don't instantiate the `login` variable here; it should be lazily instantiated:
    # http://blog.jayfields.com/2007/07/ruby-lazily-initialized-attributes.html
  end

  # Use snake_case for method names
  # https://github.com/rubocop-hq/ruby-style-guide#naming
  def new_user
    puts 'What is the name of the user you would like to add?'
    user = gets.chomp

    puts 'What is the password you would add?'
    # Suppress local echo of the password as it is typed
    # https://stackoverflow.com/a/29334534/3784008
    pass = STDIN.noecho(&:gets).chomp

    # Do not call .to_sym on pass; if pass == an Integer then it will raise an exception,
    # e.g., 1.to_sym => NoMethodError: undefined method `to_sym' for 1:Integer
    { user => pass }
  end
end

然后像以前一样运行它:

you_bank = Bank.new
Welcome to HEIDI BANK!
=> #<Bank:0x00007f8cc9086710>
you_bank.new_user
What is the name of the user you would like to add?
foo
What is the password you would add?
=> {"foo"=>"bar"}

关于原始代码的另外两个注释:

  1. 请勿使用全局变量(变量名前面带有$)。 this answer有更多说明。如果最终需要在类的实例中访问的变量,则应使用instance variable
  2. 编写DRY code。不需要add(keyVal)方法,因为Hash已经在merge中实现了该方法。尝试将您要解决的问题翻译成可以搜索的内容,在这种情况下,您要“ 添加到ruby中的哈希”,并且该查询的第一个Google结果是this answer详细说明了操作方法。

希望这对您有所帮助。

更新

您在下面问“什么是惰性实例化?”简短的答案是:在需要使用变量之前不要分配变量。例如:

# Bad; don't do this
class Foo
  def initialize
    # This variable is instantiated when calling `Foo.new`, 
    # before it needs to be used, and so takes up memory right 
    # away vs. only once it's needed
    @variable_used_by_example_method = 'foobar'
  end

  def example_method
    puts @variable_used_by_example_method
  end
end

# Better; okay to do this
class Foo
  def initialize
  end

  def example_method
    # This variable is lazily instantiated, that is, it is not 
    # instantiated until `Foo.new.example_method` is called
    @variable_used_by_example_method = 'foobar'
    puts @variable_used_by_example_method
  end
end

关于将用户名和密码与用户键入的内容进行比较的其他问题,我建议您仔细考虑一下问题,如果仍然不确定,请发布新问题。您提出的问题尚不清楚,我无法给您一个很好的答案。现在,您正在尝试使用代码来确定一切工作原理,并且当您进行尝试和学习时,可以做一些不完全符合面向对象编程设计模式的事情。但是,根据您到目前为止告诉我的内容,我给您的任何答案都可能与这些模式背道而驰,或者太高级了。 (例如,在类似Rails的框架中使用数据库和相关模型)

我不会做第一个,因为那将是一个不好的建议,而我不会做第二个,因为您应该对Ruby和编程有更牢固的了解。因此,我建议您通过以下方式考虑这些问题:

  1. 您对总体目标的简单英语逐步解释是什么?
  2. 该解释如何用面向对象的逻辑来描述?
  3. 您可以编写哪些代码来封装该逻辑?
  4. 您描述逻辑的能力与编写该逻辑代码的能力之间有何差距?

然后,您可以开始提出具体问题,以填补这些空白。