你如何从initialize方法调用类方法?

时间:2016-04-21 00:35:58

标签: ruby class matrix object-initializers

我试图在初始化方法中调用类中的方法。这是不允许的?我最初在类之外使用了方法来尝试将其用作全局方法。当前方法尝试返回创建的矩阵,然后initialize方法将返回的矩阵保存到实例变量中。

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

执行此操作会返回此错误

`'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>'`

我想在实例化类时创建矩阵的实例变量。我也试过让setMatrix方法直接将矩阵保存到@k而不是返回矩阵,这也给出了类似的错误。我怎么做才能实现我的目标?

2 个答案:

答案 0 :(得分:6)

没有什么可以阻止你在initialize内调用方法,那里没有特殊的行为,但你在这里调用的是另一个类中的私有方法。

我不知道为什么设置private,而有些人观察that seems to be a problem,所以你总是可以强制它:

matrix.send(:[]=, 1, 2, 3)

这看起来很混乱,并按照该帖子中的建议修补它可能有助于简化事情:

class Matrix
  def []=(row, column, value)
    @rows[row][column] = value
  end
end

您也可以将Matrix子类化为MutableMatrix并包含该方法。

作为一个注释,Ruby的方法命名约定为underscore_style,并且在最后包含一个显式的return是不必要的,这是隐含的。仅m就可以完成这项工作。

答案 1 :(得分:1)

让我们获取更多信息:

GCD(a, b) = a == b ? a : GCD(min(a, b), abs(a-b))

后者对我来说是一个惊喜。考虑到require 'matrix' Matrix.instance_methods.include?(:[]=) #=> false Matrix.private_instance_methods.include?(:[]=) #=> true 对象是不可变的,应该没有Matrix方法。 (它类似于:[]=,当然会引发异常。)也许Ruby使用它来实现2=4方法。读者可以解释为什么这种无证的私有方法存在吗?

如果您希望使用该私有实例方法,您可以像@tadman建议的那样使用。

我的建议是使用Matrix#build。 (我已将Matrix重命名为setMatrix以符合Ruby的命名方法和变量约定。)

set_matrix

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