Type of links to objects in ruby

I am new to Ruby and am currently trying out a few examples from a Ruby book that I use as a guide:

    class Account
attr_accessor :balance
def initialize(balance)
  @balance = balance
end  
end

class Transaction
def initialize(account_a, account_b)
@account_a = account_a
@account_b = account_b  
end  

def debit(account,amount)
  account.balance -= amount
end
    def credit(account,amount)
        account.balance += amount
    end

  def transfer(amount)
      debit(@account_a, amount)
      credit(@account_b, amount)    
  end

end

savings = Account.new(100)
checking = Account.new(200)
trans = Transaction.new(checking, savings)
trans.transfer(60)

puts savings.balance
puts checking.balance

This is a fairly simple example containing two classes in one script file. I am confused by the type of argument I pass on to lending and debit methods. Based on Java, I still understand types, so obviously, the type of account variable that I am going to, for example, the debit method, must be of type Account.

Since ruby ​​is dynamically typed and does not check the type, how can I safely work with the argument I pass and determine the rest of the method by specifying: account.balance - + amount?

Am I trying to understand what kind of security exists if I pass a link to an object other than an account to the debit method?

, . , , , ... ( , ) , , , ( )? , , , Account.

def credit(account,amount)
        account.balance += amount
    end

, , ?

, - , . , , java.

.

+3
4

Ruby. , Ruby, , . - , Ruby , . , (+ - ), NoMethodError, .

, : . , , , , - , . , , , . Ruby . , , (raise 'WTF?' unless object.class == String), ( to_foo -type).

. , , . mocks proxies .

+3

"duck typing" - , , - .

+2

, - ,


, ​​ vs-static.

, :

Ruby , , . . (, , , .)

, - .

, .

, "" . . , ... Ruby , . , , unit test, ?:-) "Duck typing ", , Ruby, .

, , Java Scala, , , . , 1- .

+1

, , , Ruby ; , , " " . .

.

case :

class Account
  attr :balance # add ", true" to make it writeable
  def initialize(balance)
    case balance
      when String: @balance = balance.to_f
      when Fixnum, Float: @balance = balance
    else
      raise TypeError, "Can't initialize an account with a balance of type #{obj.class}."
    end
  end
end

Another option, when you have to run one test, is an is_a?object tag , for example it obj.is_a?(Fixnum)will return true / false if it is an integer.

You can use the statement to enforce the type:

class Account
  attr :balance # add ", true" to make it writeable
  def initialize(balance)
    assert_eql balance.class, Float
    @balance = balance
  end
end

I would suggest that for the Transaction class, you use an if-statement in conjunction with raising an exception:

class Transaction
  def initialize(account_a, account_b)
    raise ParameterError, "Both parameters must be accounts!" unless account_a.is_a?(Account) && account_b.is_a?(Account)
    @account_a = account_a
    @account_b = account_b  
  end

  def transfer(amount)
    debit(@account_a, amount)
    credit(@account_b, amount)    
  end

  private

  def debit(account,amount)
    account.balance -= amount
  end

  def credit(account,amount)
    account.balance += amount
  end
end
+1
source

Source: https://habr.com/ru/post/1718515/


All Articles