首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从初始化方法调用类方法?

如何从初始化方法调用类方法?
EN

Stack Overflow用户
提问于 2016-04-21 00:35:57
回答 2查看 4.7K关注 0票数 2

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

代码语言:javascript
复制
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

这样做会返回此错误。

代码语言:javascript
复制
`'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,而不是返回矩阵,这会产生类似的错误。我还能做些什么来实现我想要的呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-21 00:45:39

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

我不知道为什么设置为private,而且有些人观察到了这似乎是个问题,所以你总是可以用暴力强迫它:

代码语言:javascript
复制
matrix.send(:[]=, 1, 2, 3)

这似乎很麻烦,按照那篇文章中的建议进行修补可能有助于简化事情:

代码语言:javascript
复制
class Matrix
  def []=(row, column, value)
    @rows[row][column] = value
  end
end

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

值得注意的是,Ruby对方法的命名约定是underscore_style,并且在最后包含一个显式的return是不必要的,这是隐含的。只有m才能胜任这项工作。

票数 6
EN

Stack Overflow用户

发布于 2016-04-21 01:57:05

让我们获得更多信息:

代码语言:javascript
复制
require 'matrix'
Matrix.instance_methods.include?(:[]=)
  #=> false
Matrix.private_instance_methods.include?(:[]=)
  #=> true

后者对我来说是个惊喜。考虑到Matrix对象是不可变的,不应该有:[]=方法。(这类似于2=4,这当然会引发一个例外。)也许它被Ruby用来实现Matrix方法。读者能解释为什么这种无文档化的私有方法存在吗?

如果您希望使用这个私有实例方法,您可以按照@tadman的建议来做。

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

代码语言:javascript
复制
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

代码语言:javascript
复制
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]]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36757608

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档