你如何从初始化方法中调用 class 方法?
How do you call class method from initialize method?
我试图在 class 的初始化方法中调用方法。这是不允许的吗?我最初有 class 之外的方法来尝试将其用作全局方法。当前方法尝试 return 创建的矩阵,然后初始化方法将 returned 矩阵保存到实例变量中。
class Member
def setMatrix(a, i, l)
puts "here"
m = Matrix.zero(6)
m[0,0] = a*l**2/i
m[0,3] = -a*l**2/i
m[1,1] = 12
m[1,2] = 6*l
m[1,4] = -12
m[1,5] = 6*l
m[2,1] = 6*l
m[2,2] = 4*l**2
m[2,4] = -6*l
m[2,5] = 2*l**2
m[3,0] = -a*l**2/i
m[3,3] = a*l**2/i
m[4,1] = -12
m[4,2] = -6*l
m[4,4] = 12
m[4,5] = -6*l
m[5,1] = 6*l
m[5,2] = 2*l**2
m[5,4] = -6*l
m[5,5] = 4*l**2
return m
#@k = m
end
def initialize(a, i, l)
@area = a
@i = i
@length = l
@k = setMatrix(a, i, l)
end
end
这样做 return 出现这个错误
`'setMatrix': private method '[]=' called for #<Matrix:0x00000001186e00> (NoMethodError)
from truss_solver.rb:71:in 'initialize'
from truss_solver.rb:86:in 'new'
from truss_solver.rb:86:in 'block in <main>'
from truss_solver.rb:85:in 'each'
from truss_solver.rb:85:in '<main>'`
我希望它在实例化 class 时创建一个矩阵的实例变量。我还尝试让 setMatrix 方法将矩阵直接保存到 @k 而不是 returning 矩阵,这给出了类似的错误。我还能做些什么来实现我想要的?
没有什么可以阻止您在 initialize
中调用方法,那里没有特殊行为,但是您在这里调用的是另一个中的 private 方法class.
我不知道为什么设置 private
,有些人已经观察到 that seems to be a problem,所以你总是可以暴力破解它:
matrix.send(:[]=, 1, 2, 3)
这看起来很乱,按照 post 中的建议对其进行修补可能有助于简化事情:
class Matrix
def []=(row, column, value)
@rows[row][column] = value
end
end
您还可以将 class Matrix
子MutableMatrix
并包含该方法。
请注意,Ruby 的方法命名约定是 underscore_style
并且在末尾包含一个明确的 return
不是必需的,这是隐含的。 m
一个人就够了。
让我们了解更多信息:
require 'matrix'
Matrix.instance_methods.include?(:[]=)
#=> false
Matrix.private_instance_methods.include?(:[]=)
#=> true
后者让我大吃一惊。考虑到 Matrix
对象是不可变的,所以不应该有 :[]=
方法。 (它类似于 2=4
,这当然会引发异常。)也许它被 Ruby 用于实现 Matrix
方法。 reader 可以解释为什么存在这个未记录的私有方法吗?
如果您希望使用该私有实例方法,您可以按照@tadman 的建议进行操作。
我的建议是使用 Matrix#build。 (我已将 setMatrix
重命名为 set_matrix
以符合 Ruby 命名方法和变量的约定。)
class Member
def set_matrix(a, i, l)
Matrix.build(6) do |r,c|
case [r,c].sort
when [0,0], [3,3] then a*l**2/i
when [0,3] then -a*l**2/i
when [1,1], [4,4] then 12
when [1,4] then -12
when [1,2], [1,5] then 6*l
when [2,4], [4,5] then -6*l
when [2,2], [5,5] then 4*l**2
when [2,5] then 2*l**2
else 0
end
end
end
def initialize(a, i, l)
@area = a
@i = i
@length = l
@k = set_matrix(a, i, l)
end
end
m = Member.new(1,2,3).instance_variable_get(:@k)
#=> Matrix[[ 4, 0, 0, -5, 0, 0],
# [ 0, 12, 18, 0, -12, 18],
# [ 0, 18, 36, 0, -18, 18],
# [-5, 0, 0, 4, 0, 0],
# [ 0, -12, -18, 0, 12, -18],
# [ 0, 18, 18, 0, -18, 36]]
我试图在 class 的初始化方法中调用方法。这是不允许的吗?我最初有 class 之外的方法来尝试将其用作全局方法。当前方法尝试 return 创建的矩阵,然后初始化方法将 returned 矩阵保存到实例变量中。
class Member
def setMatrix(a, i, l)
puts "here"
m = Matrix.zero(6)
m[0,0] = a*l**2/i
m[0,3] = -a*l**2/i
m[1,1] = 12
m[1,2] = 6*l
m[1,4] = -12
m[1,5] = 6*l
m[2,1] = 6*l
m[2,2] = 4*l**2
m[2,4] = -6*l
m[2,5] = 2*l**2
m[3,0] = -a*l**2/i
m[3,3] = a*l**2/i
m[4,1] = -12
m[4,2] = -6*l
m[4,4] = 12
m[4,5] = -6*l
m[5,1] = 6*l
m[5,2] = 2*l**2
m[5,4] = -6*l
m[5,5] = 4*l**2
return m
#@k = m
end
def initialize(a, i, l)
@area = a
@i = i
@length = l
@k = setMatrix(a, i, l)
end
end
这样做 return 出现这个错误
`'setMatrix': private method '[]=' called for #<Matrix:0x00000001186e00> (NoMethodError)
from truss_solver.rb:71:in 'initialize'
from truss_solver.rb:86:in 'new'
from truss_solver.rb:86:in 'block in <main>'
from truss_solver.rb:85:in 'each'
from truss_solver.rb:85:in '<main>'`
我希望它在实例化 class 时创建一个矩阵的实例变量。我还尝试让 setMatrix 方法将矩阵直接保存到 @k 而不是 returning 矩阵,这给出了类似的错误。我还能做些什么来实现我想要的?
没有什么可以阻止您在 initialize
中调用方法,那里没有特殊行为,但是您在这里调用的是另一个中的 private 方法class.
我不知道为什么设置 private
,有些人已经观察到 that seems to be a problem,所以你总是可以暴力破解它:
matrix.send(:[]=, 1, 2, 3)
这看起来很乱,按照 post 中的建议对其进行修补可能有助于简化事情:
class Matrix
def []=(row, column, value)
@rows[row][column] = value
end
end
您还可以将 class Matrix
子MutableMatrix
并包含该方法。
请注意,Ruby 的方法命名约定是 underscore_style
并且在末尾包含一个明确的 return
不是必需的,这是隐含的。 m
一个人就够了。
让我们了解更多信息:
require 'matrix'
Matrix.instance_methods.include?(:[]=)
#=> false
Matrix.private_instance_methods.include?(:[]=)
#=> true
后者让我大吃一惊。考虑到 Matrix
对象是不可变的,所以不应该有 :[]=
方法。 (它类似于 2=4
,这当然会引发异常。)也许它被 Ruby 用于实现 Matrix
方法。 reader 可以解释为什么存在这个未记录的私有方法吗?
如果您希望使用该私有实例方法,您可以按照@tadman 的建议进行操作。
我的建议是使用 Matrix#build。 (我已将 setMatrix
重命名为 set_matrix
以符合 Ruby 命名方法和变量的约定。)
class Member
def set_matrix(a, i, l)
Matrix.build(6) do |r,c|
case [r,c].sort
when [0,0], [3,3] then a*l**2/i
when [0,3] then -a*l**2/i
when [1,1], [4,4] then 12
when [1,4] then -12
when [1,2], [1,5] then 6*l
when [2,4], [4,5] then -6*l
when [2,2], [5,5] then 4*l**2
when [2,5] then 2*l**2
else 0
end
end
end
def initialize(a, i, l)
@area = a
@i = i
@length = l
@k = set_matrix(a, i, l)
end
end
m = Member.new(1,2,3).instance_variable_get(:@k)
#=> Matrix[[ 4, 0, 0, -5, 0, 0],
# [ 0, 12, 18, 0, -12, 18],
# [ 0, 18, 36, 0, -18, 18],
# [-5, 0, 0, 4, 0, 0],
# [ 0, -12, -18, 0, 12, -18],
# [ 0, 18, 18, 0, -18, 36]]