不合逻辑:逻辑循环,在 ruby 中使用 'super'
Illogical: circle of logic, in ruby using 'super'
我一直在尝试根据继承父 class 功能的子 class 中方法的功能进行推理。但似乎我一直陷入这样的心理循环:one 没有 other 但 other 不能出现在 one[=56 之前=]...脑子疼...
好的,这是我在父级中的相关代码 class
class BankAccount
# method to initialize and other methods etc...
def withdraw(amount)
if (amount <= @balance)
@balance -= amount
else
'Insufficient funds'
end
end
end
这是我在子class
中的相关代码
class CheckingAccount < BankAccount
# methods to initialize and other methods etc...
def withdraw
super
end
end
根据我正在学习的教程 - 我想要完成的是
- "CheckingAccount methods #withdraw increments 'number_of_withdrawals' by one after a successful withdrawal"
因此,如果我在我的 BankAccount
class 中创建一个变量 number_of_withdrawals
(如教程示例所暗示的那样),那么当我从withdraw
的 subclass 版本,它将根据 if
else
语句是否执行撤回而知道增加 number_of_withdrawals
。
不应该在 BankAccount
class 中声明变量 number_of_withdrawals
,而不是 CheckingAccount
class(即使教程示例暗示要将它在 CheckingAccount
class 中)。要全面了解这一点,请查看我当前代码状态下方的测试规范 () 的要点:
如果有人可以提供
的工作示例
- "CheckingAccount methods #withdraw increments 'number_of_withdrawals' by one after a successful withdrawal"
我在 GIST 中提供了经过修改的代码 - 我将非常感激。我对 ruby 很陌生。(1 周)
使用目前编写的代码,CheckingAccount#withdraw
可以检查 super
的 return 值来确定提款是否成功。
例如:
def withdraw(n)
result = super
if result != 'Insufficient funds'
@number_of_withdrawals += 1
end
result
end
您看到的行为——或预期为完成练习而提供的行为——是由于 Ruby 的 dynamic nature。由于您的程序是 "interpreted",因为它是 运行(并且可能会发生变化),因此 Ruby 无法知道所讨论的实例变量将不存在,直到该方法实际上是已执行。
这是一个人为的例子,它(希望)展示了为什么你 seeing/hoping 看到这种行为:
class Foo
def say_something_that_doesnt_exist
# Foo is free to try to make use of @nothing,
# in case it's been provided by a child class'
# instance, but if it's not present, its value
# will just be nil
puts "say_something_that_doesnt_exist, like #{@nothing}!"
end
def say_something_that_does_exist
puts "say_something_that_does_exist, like #{@bar}!"
end
end
class Bar < Foo
attr_reader :bar
def initialize
super
@bar = "bar"
end
end
bar = Bar.new
bar.say_something_that_doesnt_exist # say_something_that_doesnt_exist, like !
bar.say_something_that_does_exist # say_something_that_does_exist, like bar!
您应该查看 this 问题及其答案,以更详细地讨论 static/dynamic 语言与 early/late 值绑定之间的区别。
你的方法做的太多了,内化了太多的假设。一个更好的方法是稍微分解一下:
class BankAccount
attr_reader :balance
def initialize
@balance = 0
end
def withdraw(amount)
if (can_withdraw?(amount))
credit(amount)
after_withdraw
else
false
end
end
def can_withdraw?(amount)
amount <= balance
end
def after_withdraw
# No default behaviour
end
def debit(amount)
@balance += amount
end
def credit(amount)
@balance -= amount
end
end
然后你可以让子类专门化非常具体的方法,而不必如此努力地依赖 super
:
class CheckingAccount < BankAccount
attr_reader :overdraft
def initialize
super
@overdraft = 0
@withdrawals = 0
end
def can_withdraw?(amount)
amount <= balance + overdraft
end
def after_withdraw
@withdrawals += 1
end
end
通过继承,parent 可以被认为是 child 的 'template'。也就是说,您完全可以不使用 parent 而只是将所有内容写入 child class(不是您应该这样做)。关键是 parent class 中的所有内容都可以被认为是被复制到 child class 上,所以如果你在 [=35] 上创建一个实例变量=] 并将其从 child 更改为,只定义了一个实例变量,因为只有一个 object 被实例化。换句话说,当你说 CheckingAccount.new
时,没有 separate BankAccount
被实例化——它们都是一样的 object。
因此,对于在 parent 和 child 中定义的每个方法,您需要调用 super
否则 parent 方法不会被调用。这是您的代码示例:
class BankAccount
def initialize
@balance = 0
@number_of_withdrawals = 0
end
def withdraw(amount)
if amount <= @balance
@balance -= amount
@number_of_withdrawals += 1
else
'Insufficient funds'
end
end
end
class CheckingAccount < BankAccount
MAX_FREE_WITHDRAWALS = 3
def withdraw(amount)
if @number_of_withdrawals >= self.class::MAX_FREE_WITHDRAWALS
amount += 5
super(amount)
end
end
我只是浏览了需求文档,所以一定要仔细检查(例如,不要只拿我的代码,然后把它当作作业 :D)
我一直在尝试根据继承父 class 功能的子 class 中方法的功能进行推理。但似乎我一直陷入这样的心理循环:one 没有 other 但 other 不能出现在 one[=56 之前=]...脑子疼...
好的,这是我在父级中的相关代码 class
class BankAccount
# method to initialize and other methods etc...
def withdraw(amount)
if (amount <= @balance)
@balance -= amount
else
'Insufficient funds'
end
end
end
这是我在子class
中的相关代码class CheckingAccount < BankAccount
# methods to initialize and other methods etc...
def withdraw
super
end
end
根据我正在学习的教程 - 我想要完成的是
- "CheckingAccount methods #withdraw increments 'number_of_withdrawals' by one after a successful withdrawal"
因此,如果我在我的 BankAccount
class 中创建一个变量 number_of_withdrawals
(如教程示例所暗示的那样),那么当我从withdraw
的 subclass 版本,它将根据 if
else
语句是否执行撤回而知道增加 number_of_withdrawals
。
不应该在 BankAccount
class 中声明变量 number_of_withdrawals
,而不是 CheckingAccount
class(即使教程示例暗示要将它在 CheckingAccount
class 中)。要全面了解这一点,请查看我当前代码状态下方的测试规范 () 的要点:
如果有人可以提供
的工作示例- "CheckingAccount methods #withdraw increments 'number_of_withdrawals' by one after a successful withdrawal"
我在 GIST 中提供了经过修改的代码 - 我将非常感激。我对 ruby 很陌生。(1 周)
使用目前编写的代码,CheckingAccount#withdraw
可以检查 super
的 return 值来确定提款是否成功。
例如:
def withdraw(n)
result = super
if result != 'Insufficient funds'
@number_of_withdrawals += 1
end
result
end
您看到的行为——或预期为完成练习而提供的行为——是由于 Ruby 的 dynamic nature。由于您的程序是 "interpreted",因为它是 运行(并且可能会发生变化),因此 Ruby 无法知道所讨论的实例变量将不存在,直到该方法实际上是已执行。
这是一个人为的例子,它(希望)展示了为什么你 seeing/hoping 看到这种行为:
class Foo
def say_something_that_doesnt_exist
# Foo is free to try to make use of @nothing,
# in case it's been provided by a child class'
# instance, but if it's not present, its value
# will just be nil
puts "say_something_that_doesnt_exist, like #{@nothing}!"
end
def say_something_that_does_exist
puts "say_something_that_does_exist, like #{@bar}!"
end
end
class Bar < Foo
attr_reader :bar
def initialize
super
@bar = "bar"
end
end
bar = Bar.new
bar.say_something_that_doesnt_exist # say_something_that_doesnt_exist, like !
bar.say_something_that_does_exist # say_something_that_does_exist, like bar!
您应该查看 this 问题及其答案,以更详细地讨论 static/dynamic 语言与 early/late 值绑定之间的区别。
你的方法做的太多了,内化了太多的假设。一个更好的方法是稍微分解一下:
class BankAccount
attr_reader :balance
def initialize
@balance = 0
end
def withdraw(amount)
if (can_withdraw?(amount))
credit(amount)
after_withdraw
else
false
end
end
def can_withdraw?(amount)
amount <= balance
end
def after_withdraw
# No default behaviour
end
def debit(amount)
@balance += amount
end
def credit(amount)
@balance -= amount
end
end
然后你可以让子类专门化非常具体的方法,而不必如此努力地依赖 super
:
class CheckingAccount < BankAccount
attr_reader :overdraft
def initialize
super
@overdraft = 0
@withdrawals = 0
end
def can_withdraw?(amount)
amount <= balance + overdraft
end
def after_withdraw
@withdrawals += 1
end
end
通过继承,parent 可以被认为是 child 的 'template'。也就是说,您完全可以不使用 parent 而只是将所有内容写入 child class(不是您应该这样做)。关键是 parent class 中的所有内容都可以被认为是被复制到 child class 上,所以如果你在 [=35] 上创建一个实例变量=] 并将其从 child 更改为,只定义了一个实例变量,因为只有一个 object 被实例化。换句话说,当你说 CheckingAccount.new
时,没有 separate BankAccount
被实例化——它们都是一样的 object。
因此,对于在 parent 和 child 中定义的每个方法,您需要调用 super
否则 parent 方法不会被调用。这是您的代码示例:
class BankAccount
def initialize
@balance = 0
@number_of_withdrawals = 0
end
def withdraw(amount)
if amount <= @balance
@balance -= amount
@number_of_withdrawals += 1
else
'Insufficient funds'
end
end
end
class CheckingAccount < BankAccount
MAX_FREE_WITHDRAWALS = 3
def withdraw(amount)
if @number_of_withdrawals >= self.class::MAX_FREE_WITHDRAWALS
amount += 5
super(amount)
end
end
我只是浏览了需求文档,所以一定要仔细检查(例如,不要只拿我的代码,然后把它当作作业 :D)