不使用Ruby-Bank Program中的全局变量,无法获得2个单独的类来相互交互

时间:2014-05-26 20:19:15

标签: ruby

这里有新用户和第一次海报!我是Ruby的新手,正在研究"应该"是一个简单的银行程序,我必须在其中提出代码以产生给定的输出和方法调用。我似乎很顺利地走了一段路,但遇到了一个主要的障碍,我的两个班级(银行和个人)没有正确地相互沟通。我在我的person类中提出了一个使用全局变量的解决方案,以便银行类可以访问它,但后来看到了我应该避免全局变量的地方。我目前正试图在不使用全局变量的情况下让类进行通信,而且每当我调用我的" open_account"方法,该方法无法从Person类中提取名称(@pname)。

在过去的8-9天里,我已经看了一遍,甚至还买了另一本Ruby书,但是他们似乎都没有关于如何直接让两个单独的类互相交互而没有它们的示例/教程彼此继承或使用模块等。我只是希望Bank类能够在调用不同的bank方法时使用Person类中的Name和Cash等。

由于我想解决沟通问题所以你可以忽略银行类中的这两种方法,因此我还没有真正尝试完成存款和转账方式。预期的输出在我目前的结尾处被评论。关于我如何能够实现这一目标的任何建议?我对Ruby非常陌生,并且认为我已经理解了它,但仍然承认我仍然非常粗糙。提前谢谢!

哦,最后一件事,当我使用全局变量来访问我的人物对象时,我会在所有的地方输出创建的最后一个人对象人物对象创建。这显然不是这样的,因为我已经远离了全局变量使用,但我仍然对它为什么会发生这种情况感到好奇?谢谢!

更新 我的更新代码低于原始代码,但我的余额似乎是单一余额,而不是每个人都拥有自己的代码。我得到的输出低于更新后的代码。

class Bank

  def initialize(bname, withdrawal=0, deposit=0, transfer=0)
    @bname = bname
    @withdrawal = withdrawal
    @deposit = deposit
    @transfer = transfer
    puts "#{@bname} bank was just created."
  end

  def open_account(pname)
    puts "#{@pname}, thanks for opening an account at #{@bname}!"
  end

  def withdrawal(amount)
    @balance -= amount
    puts "#{@pname} withdrew $#{amount} from #{@bname}.  #{@pname} has #{@balance}.  #{@pname}'s account has #{@balance}."
  end

  def deposit(pname, amount)
    @balance += amount
    puts "#{@pname} deposited $#{amount} to #{@bname}.  #{@pname} has #{@balance}.  #{@pname}'s account has #{@balance}."
  end


  def transfer(pname, bname, amount)
    if @pname == pname
      @balance -= amount
      @transfer = amount
      puts "You have transferred $#{amount} from your account.  Your new balance is $#{@balance}."
    else
      puts "Incorrect username."
    end
  end
end

class Person

  def initialize(pname, cash)
    @pname = pname
    @cash = cash
    puts "Hi, #{@pname}.  You have #{@cash}!"
  end

end

chase = Bank.new("JP Morgan Chase")
wells_fargo = Bank.new("Wells Fargo")
person1 = Person.new("John", 1000)
person2 = Person.new("Lloyd", 5000)
chase.open_account(person1)
chase.open_account(person2)
wells_fargo.open_account(person1)
wells_fargo.open_account(person2)
#chase.deposit(person1, 200)
#chase.deposit(person2, 350)
#chase.withdrawal(person1, 500)

=begin #What should be ouput
JP Morgan Chase bank was just created.
Wells Fargo bank was just created.
Hi, John. You have $1000!
Hi, Lloyd. You have $5000!
John, thanks for opening an account at JP Morgan Chase!
Lloyd, thanks for opening an account at JP Morgan Chase!
John, thanks for opening an account at Wells Fargo!
Lloyd, thanks for opening an account at Wells Fargo!
=end

****更新了代码*****

class Bank

  def initialize(bname, balance = 0, withdrawal=0, deposit=0, transfer=0)
    @bname = bname
    @withdrawal = withdrawal
    @deposit = deposit
    @transfer = transfer
    @balance = balance
    puts "#{@bname} bank was just created."
  end

  def open_account(name, balance = 0)
    @balance = balance
    puts "#{name}, thanks for opening an account at #{@bname}!"
  end


  def withdrawal(name, amount)
    @balance -= amount
    puts "#{name} withdrew $#{amount} from #{@bname}.  #{name} has #{@balance}.  #{name}'s account has #{@balance}."
  end

  def deposit(name, amount)
    @balance += amount
    puts "#{name} deposited $#{amount} to #{@bname}.  #{name} has #{@balance}.  #{name}'s account has #{@balance}."
  end

  def transfer(name, bname, amount)
    if name == name
      @balance -= amount
      @transfer = amount
      puts "#{name} have transfered $#{amount} from #{@bname} account to #{@bname}.  Your new balance is $#{@balance}."
    else
      puts "Incorrect username."
    end
  end
end

class Person

  attr_accessor :name, :cash
  def initialize(name, cash = 100)
    @name = name
    @cash = cash
    puts "Hi, #{name}.  You have $#{cash} on hand!"
  end

end

chase = Bank.new("JP Morgan Chase")
wells_fargo = Bank.new("Wells Fargo")
randy = Person.new("Randy", 1000)
kristen = Person.new("Kristen", 5000)
justin = Person.new("Justin", 1500)
chase.open_account('Randy')
chase.open_account('Kristen')
chase.open_account('Justin')
wells_fargo.open_account('Randy')
wells_fargo.open_account('Kristen')
chase.deposit("Randy", 200)
chase.deposit("Kristen", 350)
chase.withdrawal("Kristen", 500)
chase.transfer("Randy", wells_fargo, 100)

=begin #updated code output
JP Morgan Chase bank was just created.
Wells Fargo bank was just created.
Hi, Randy.  You have $1000 on hand!
Hi, Kristen.  You have $5000 on hand!
Hi, Justin.  You have $1500 on hand!
Randy, thanks for opening an account at JP Morgan Chase!
Kristen, thanks for opening an account at JP Morgan Chase!
Justin, thanks for opening an account at JP Morgan Chase!
Randy, thanks for opening an account at Wells Fargo!
Kristen, thanks for opening an account at Wells Fargo!
Randy deposited $200 to JP Morgan Chase.  Randy has 200.  Randy's account has 200.
Kristen deposited $350 to JP Morgan Chase.  Kristen has 550.  Kristen's account has 550.
Kristen withdrew $500 from JP Morgan Chase.  Kristen has 50.  Kristen's account has 50.
Randy have transfered $100 from JP Morgan Chase account to JP Morgan Chase.  Your new balance is $-50.
=end

2 个答案:

答案 0 :(得分:1)

ruby​​中的对象通过向这些对象公开方法与其他对象进行通信。您的Person类的实例可以在内部访问instance variables,但这些实例变量不应在外部公开。

任何带有@符号前缀的变量都是实例变量,这意味着@pname只能由您的人物对象访问,而@bname只能由您的银行对象访问

从银行对象访问@pname实例变量的方法是在Person类上公开实例方法,以便调用Bank类的实例。

class Person
  def initialize(name)
    @name = name
  end

  def name
    @name
  end
end

john = Person.new("John Doe")
john.name # => "John Doe"

在此示例中,您不是直接访问@name实例变量,而是在其周围添加一个间接层。这很好,因为它允许更多的灵活性 - 假设不是将人的整个名字存储在一个变量中,而是分别存储他们的名字和姓氏:

class Person
  def initialize(first_name, last_name)
    @first_name = first_name
    @last_name = last_name
  end

  def name
    "#{@first_name} #{@last_name}"
  end
end  

john = Person.new("John", "Doe")
john.name # => "John Doe"

即使存储人名的内部实现与第一个示例不同,公共接口也没有改变:在这两种情况下,调用person#name都会返回该人的姓名。

如果你想直接暴露一个实例变量而不需要任何进一步的操作,Ruby提供了几个ways来为你生成这些实例方法,而不需要你做任何进一步的努力。它们如下:

  1. attr_reader
  2. attr_writer
  3. attr_accessor
  4. attr_reader可以像这样使用:

    class Person
      attr_reader :name
      def initialize(name)
        @name = name
      end
    end
    
    john = Person.new("John")
    john.name # => "John"
    

    在幕后,它会生成以下定义

    def name
      @name
    end
    

    attr_writer可以按如下方式使用:

    class Person
      attr_writer :name
      def name
        @name
      end
    end
    
    john = Person.new
    john.name # => nil
    john.name = "John"
    john.name # => "John"
    

    在幕后,attr_writer定义了一个方法,允许您在person对象的上下文之外设置@name实例变量:

    def name=(name)
      @name = name
    end
    

    如果要同时创建setter方法和getter方法,可以执行以下操作:

    class Person
      attr_reader :name
      attr_writer :name
    end
    

    等效地,你可以使用attr_accessor一次创建getter和setter:

    class Person
      attr_accessor :name
    end
    
    john = Person.new
    john.name # => nil
    john.name = "John"
    john.name # => "John"
    

    所有这些的结论是,在Ruby中,对象通过相互调用方法相互通信,而不是通过访问不属于它们的实例变量。

答案 1 :(得分:0)

这个问题(恕我直言)正在为一个帐户对象而哭泣。帐户对象可以保存在Bank对象内的数组中。每个Account对象都包含一个Person对象,而该Person对象只包含该Bank的余额。您目前的结构方式是,开设帐户的最后一个人是唯一拥有帐户的人。

一些标本库方法......

  def open_account(person, initial_deposit = 0)
    @accounts << Account.new(person)
    puts "#{person.pname}, thanks for opening an account at #{@bname}!"
    deposit person, initial_deposit unless initial_deposit == 0
  end

  def deposit(person, amount)
    account = @accounts.select{|a| a.person == person}.first
    if account
      if person.cash < amount
        puts "#{person.pname} doesn't have that much to deposit"
      else
        account.balance += amount
        person.cash -= amount
      end
    else
      puts "no account found for #(person.pname}"
    end
  end