2016-04-21 5 views
1

Ich versuche, eine Methode in einer Klasse während seiner Initialisierungsmethode aufzurufen. Ist das nicht erlaubt? Ich hatte ursprünglich die Methode außerhalb der Klasse, um sie als globale Methode zu verwenden. Die aktuelle Methode versucht, die erstellte Matrix zurückzugeben, und dann speichert die Initialisierungsmethode die zurückgegebene Matrix in einer Instanzvariablen.Wie rufen Sie die Methode class from initialize auf?

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 

dies tun gibt diesen Fehler zurück

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

ich möchte es eine Instanzvariable einer Matrix machen, wenn die Klasse instanziiert wird. Ich habe auch versucht, die Methode setMatrix zu speichern, um die Matrix in @k direkt zu speichern, anstatt die Matrix zurückzugeben, und das gab einen ähnlichen Fehler. Wie kann ich sonst noch erreichen, was ich will?

+0

„Du hast gesagt,‚dies zu tun‘gibt diesen Fehler zurück ...“ Vermutlich " dies "beinhaltet die Erzeugung einer Instanz von" Member "(zB" Member.new (1,2,3) "), die nicht gezeigt wird. –

Antwort

6

Es gibt nichts, Sie von Aufrufen von Methoden innerhalb initialize zu verhindern, gibt es kein spezielles Verhalten in da, aber was Sie fordern hier eine private Methode in einer anderen Klasse.

Ich weiß nicht, warum es private gesetzt ist, und einige Leute that seems to be a problem beobachtet haben, so können Sie immer nur Brute-Force es:

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

Das chaotisch scheint, und es wie empfohlen Patchen in diesem Beitrag könnte helfen, die Dinge zu vereinfachen:

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

Sie auch Matrix-MutableMatrix und umfassen diese Methode Unterklasse könnte.

Als Hinweis, Rubys Namenskonventionen für Methoden ist underscore_style und einschließlich einer expliziten return am Ende ist nicht notwendig, es ist impliziert. m allein würde den Job machen.

+1

Außerdem sollten Sie ArgumentError erhöhen, wenn row> = row_count || column> = column_count' um sicherzustellen, dass 'row' und' column' innerhalb der Matrix liegen. – Stefan

1

Lassen Sie uns mehr Informationen erhalten:

require 'matrix' 
Matrix.instance_methods.include?(:[]=) 
    #=> false 
Matrix.private_instance_methods.include?(:[]=) 
    #=> true 

Letzteres war eine Überraschung für mich. Wenn man bedenkt, dass Matrix Objekte unveränderlich sind, sollte es keine :[]= Methode geben. (Es ist ähnlich wie 2=4, was natürlich eine Ausnahme auslöst.) Vielleicht wird es von Ruby für die Implementierung von Matrix Methoden verwendet. Kann ein Leser erklären, warum diese undokumentierte private Methode existiert?

Wenn Sie diese private Instanzmethode verwenden möchten, können Sie tun, wie @tadman es vorschlägt.

Mein Rat ist, Matrix#build zu verwenden. (Ich habe setMatrix-set_matrix umbenannt mit Rubys Konvention entsprechen für Methoden und Variablen zu benennen.)

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]] 
+0

In der Tat überraschend. Weder '[] =', nicht seine Aliase 'set_element' und' set_component' werden in der Klasse verwendet. – Stefan

+0

Die Matrix ist symmetrisch, so dass Sie einige überflüssige r, c/c, r-Paare aus Ihrem 'wenn' mit 'case [r, c] .sort' entfernen können. Ich würde in diesem Fall auch die kompaktere Form "wenn ... dann" verwenden. – Stefan

+0

@Stefan, ich hatte nicht bemerkt, dass es symmetrisch war. Ich habe deinen (schlauen) Vorschlag aufgenommen. Vielen Dank. Können Sie in Matrix.instance_method (: [] =) # => # '" Unbound "erklären, wenn man bedenkt, dass es nicht notwendig ist, die Methode an das Matrixobjekt zu binden? –

Verwandte Themen