Die Art und Weise Sie es geschrieben haben (A.new(B.new(self))
) ist unmöglich aufgrund eines zirkuläre Referenz. Um eine Instanz von A
zu erstellen, benötigen Sie eine Instanz von B
; Um die Instanz B
zu erstellen, benötigen Sie die Instanz A
.
Es gibt einige Möglichkeiten, die Implementierung zu optimieren, um dies zu ermöglichen, aber Sie müssen zuerst dieses Huhn-und-Ei-Problem zwischen A
und B
lösen. Zum Beispiel:
class A
def initialize
@b = yield(self)
end
end
class B
def initialize(a)
@a = a
end
end
A.new { |a| B.new(a) }
Beachten Sie, dass in dem obigen Code wird a
erste initialisiert. Es wird nur im Bereich nach das Objekt erstellt worden ist.
Oder hier ist eine andere Art und Weise:
class A
def initialize
@b = B.new(self)
end
end
class B
def initialize(a)
@a = a
end
end
A.new
Wie oben, wird die Instanz von A
ersten geschaffen. Aber dieses Mal habe ich die gesamte Initialisierung auf einmal gemacht, anstatt sie innerhalb des gemeldeten Anrufs new()
aufzubauen.
Ein letztes Beispiel:
class A
attr_writer :b
def initialize
end
end
class B
def initialize(a)
@a = a
end
end
A.new.tap { |a| a.b = B.new(a) }
In diesem Beispiel habe ich voll initialisiert a
vor seinem Attribut b
definieren. Dies könnte genauso gut in zwei Zeilen Code geschrieben wurde, mit einer regulären Variable anstelle der Schließung:
a = A.new
a.b = B.new(a)
es nennt diese Art und Weise eine kreisförmige Referenz wäre, da die A-Instanz benötigt wird, B zu instanziiert, was für A, etc. benötigt wird. Sie könnten das B.new jedoch in A # initialisieren. –
Wenn Sie an diesem Punkt sind, gibt es wahrscheinlich ein besseres Design, das Sie nicht sehen. Versuchen Sie, Ihr Beispiel etwas mehr mit dem Beispielcode auszuarbeiten. – Rogue
Will 'B.new (A.new)', nicht ausreichen? – progfan