Betreff: Übergabe von Nachrichten an „this“ innerhalb der KlassendefinitionStandardmäßig bietet JMP keine guten Möglichkeiten, die Pseudo-Namespaces direkt abzufragen (sei es „Window“, „This“, „Box“ usw.).
Für Klassen könnten Sie darüber nachdenken, einen Wrapper zum Erstellen von Klassen zu erstellen. Dieser Wrapper kann dann die Instanzgeneratorfunktion erstellen und während dieser Instanzgenerierung können Sie der Klasse einen Zirkelverweis geben (beachten Sie, dass dies zu Speicherverlusten führen kann). – Stellen Sie sicher, dass Sie ein Tracking-System erstellen und eine Löschmethode bereitstellen/aufrufen, wenn die Klasse gelöscht werden soll, um Zirkelverweise usw. zu entfernen.
Hier ist ein Beispiel:
Names Default to Here( 1 );
New Namespace( "class" );
class:Get Init Args = Function( {_class},
{Default Local},
For( i = 1, i <= N Items( _class ), i++,
If( Head Name( Arg( _class, i ) ) == "Glue",
For( j = 1, j <= N Arg( Arg( _class, i ) ), j++,
If( As Name( Head Name( Arg( Arg( Arg( _class, i ), j ), 1 ) ) ) == As Name( "_create_" ),
Return( Arg( Arg( Arg( Arg( _class, i ), j ), 2 ), 1 ) )
)
)
)
);
Return( {} )
);
class:Define Class = Function( {_class},
{Default Local},
class = Expr( Define Class() );
Summation( i = 1, N Arg( _class ),
Insert Into( class, Arg( _class, i ) )
);
init args = class:Get Init Args( _class );
init redirects = Expr( __cl:_create_() );
Summation( i = 1, N Items( init args ),
If( Head Name( Arg( init args, i ) ) == "Assign",
Insert Into( init redirects, Eval Expr( Name Expr( Expr( Arg( Arg( init args, i ), 1 ) ) ) ) )
,
Insert Into( init redirects, Eval Expr( Name Expr( Expr( Arg( init args, i ) ) ) ) )
)
);
Eval( class );
ns = Namespace( "class" );
Eval( Substitute( Expr(
ns[__class__] = Function( __args__,
{__cl = New Object( __class__ )},
__cl:self = __cl;
__class_call__;
__cl
)
),
Expr( __class__ ), Arg( _class, 1 ),
Expr( __args__ ), init args,
Expr( __class_call__ ), Name Expr( init redirects )
) );
0
);
class:Define Class({
"example",
_init_ = Method( {}, 1 );
_create_ = Method( {assocArray},
For Each( {{key, setter}, _}, assocArray,
self << Insert( key, Eval Expr( Method( {value}, self:TrySetProperty( Expr( key ), value, Expr( setter ) ) ) ) )
)
);
Try Set Property = Method( {parameter, value, expression If Changed},
Match( value,
., ., //Do nothing if missing value
,
self[parameter], . //Do nothing if unchanged value
,
self[paremeter] = value; //Otherwise update the value
Eval( expression If Changed ); //and eval the expression
);
);
show = Function( {name},
show( name )
)
});
//show( namespace( "class" ) );
cls = class:example( ["A" => expr( self:show( "EXPLETIVE" ) ), "B" => Expr( thing 2 )] );
show( cls << get keys );Beachten Sie jedoch, dass JMP-Klassen lediglich verherrlichte Namespaces mit angehängten Funktionen sind (Namespaces, bei denen die angehängten Funktionen wissen, in welchem Namespace sie sich befinden).Mit regulären Namespaces und Metaprogrammierung können Sie etwas ganz Ähnliches erreichen.Und mit den regulären Namespaces macht JMP keine überflüssigen Fehler, weil es nicht in der Lage sei, auf Klassenmethoden innerhalb von Funktionen zuzugreifen und so weiter.
Übergabe von Nachrichten an „this“ innerhalb der KlassendefinitionIst es möglich, aus einer Methode heraus eine Nachricht an die Instanz einer Klasse zu übergeben?
Hier ist ein Beispiel dafür, was ich versuche:
Define Class(
"example",
x=1;
test = Method( {name, method},
<< Insert(name, method);
);
);
t = New Object( example());
// This fails to insert the blah method
t:test("blah", Method({y}, show("Blah " || char(x) || char(y))));
t:blah(6);
//This succeeds in inserting and calling the blah method
t << Insert("blah", Method({y}, show("Blah " || char(x) || char(y))));
t:blah(6);Ich vermutete, dass ich möglicherweise explizit „this << Insert“ schreiben muss, aber das führt zu einem anderen Fehler:
Define Class(
"example",
x=1;
test = Method( {name, method},
<STRONG>this << Insert(name, method);</STRONG>
);
);
t = New Object( example());
// This fails because "send expects scriptable object"
t:test("blah", Method({y}, show("Blah " || char(x) || char(y));));
t:blah(6);Ich habe auch darüber nachgedacht, Send explizit aufzurufen (die Methode kann nicht hinzugefügt werden) und this:Send (der Name Send kann nicht aufgelöst werden).
Ich habe auch darüber nachgedacht, Folgendes direkt aufzurufen:Insert (kann den Namen „Insert“ nicht auflösen) und „Insert“ (fügt die Blah-Methode erfolgreich hinzu, kann den Aufrufmechanismus jedoch nicht korrekt ausloten, sodass keine Argumente an die Methode übergeben werden).
Motivation:
Ich mache das, weil ich versuche, automatisch Getter- und Setter-Methoden für eine Liste von Klasseneigenschaften zu erstellen.Im Idealfall kann ich Folgendes tun:
Define Class(
"example",
_init_ = Method( {assocArray},
For Each({property, updateMethod}, assocArray,
Insert(key, Eval Expr(Method({value}, TrySetProperty(Expr(property), value, Expr(updateMethod)))));
);
);
TrySetProperty=Method({parameter, value, expressionIfChanged},
match(value,
., ., //Do nothing if missing value
this << Get Value(parameter), ., //Do nothing if unchanged value
this << Insert(parameter, value); //Otherwise update the value
Eval(expressionIfChanged); //and eval the expression
);
);
);
properties = Associative Array({{"prop1", Expr(ThingToDoOnUpdate1)},{"prop2", Expr(ThingToDoOnUpdate2)}});
t = New Object( example(properties));
Erweiterte statistische ModellierungAutomatisierung und SkripterstellungQualitäts- und VerfahrenstechnikBetreff: Übergabe von Nachrichten an „this“ innerhalb der KlassendefinitionDies scheint die Art von Workaround zu sein, zu der JSL Sie zwingt.
Es gibt eine Parodie-Programmiersprache namens „DreamBerd“, die sich über Programmierparadigmen lustig macht.Diese Problemumgehung ist der Art und Weise, wie die Parodiesprache mit Klassen umgeht, sehr ähnlich, ist jedoch noch komplexer.
(Ich sage nicht, dass dies Ihre Schuld ist, es ist nur eine Folge der Einschränkungen in JSL).
https://github.com/TodePond/DreamBerd
KlassenSie können Klassen erstellen, aber Sie können immer nur eine Instanz davon erstellen. Dies sollte keinen Einfluss darauf haben, wie die meisten objektorientierten Programmierer arbeiten.
class Player {
const var health = 10!
}
const var player1 = new Player()!
const var player2 = new Player()! //Error: Can't have more than one 'Player' instance!So könnten Sie das machen:
class PlayerMaker {
function makePlayer() => {
class Player {
const var health = 10!
}
const const player = new Player()!
return player!
}
}
const const playerMaker = new PlayerMaker()!
const var player1 = playerMaker.makePlayer()!
const var player2 = playerMaker.makePlayer()!
Betreff: Übergabe von Nachrichten an „this“ innerhalb der KlassendefinitionIch denke, dass dies mit der benutzerdefinierten Nachrichtenübermittlung besser gehandhabt werden könnte, aber ich kann keine Dokumentation darüber finden, wie das tatsächlich geht.Soweit ich das beurteilen kann, gibt es keine Informationen zur Implementierung eigener Nachrichten.
Betreff: Übergabe von Nachrichten an „this“ innerhalb der KlassendefinitionNachrichten rufen lediglich Methoden für Klassen auf – technisch gesehen kann man über eine Nachricht keine Funktion mit Argumenten aufrufen, aber da Methoden in JSL-Klassen Ausdrücke sind, ist das Ergebnis des Nachrichtenaufrufs eine aufrufbare Funktion.Im Grunde können Sie die Klassenmethode einfach über eine Nachricht aufrufen.
Beachten Sie die Zeile Show( clx << Add( cly ) ); Aufruf der Hinzufügen Methode über eine Nachricht.
Names Default To Here( 1 );
Define Class(
"complex",
real = 0;
imag = 0;
_init_ = Method( {a, b},
real = a;
imag = b;
);
Add = Method( {y},
PRINT( "ADDING" );
New Object( complex( real + y:real, imag + y:imag ) )
);
Sub = Method( {y},
New Object( complex( real - y:real, imag - y:imag ) )
);
Mul = Method( {y},
New Object( complex( real * y:real - imag * y:imag, imag * y:real + real * y:imag ) )
);
Div = Method( {y},
t = New Object( complex( 0, 0 ) );
mag2 = y:Magsq();
t:real = real * y:real + imag * y:imag;
t:imag = imag * y:real + real * y:imag;
t:real = t:real / mag2;
t:imag = t:imag / mag2;
t;
);
Magsq = Method( {},
real * real + imag * imag
);
Mag = Method( {},
Sqrt( real * real + imag * imag )
);
_to string_ = Method( {},
Char( real ) || " + " || Char( imag ) || "i"
);
_show_ = _to string_;
);
clx = New Object( complex( 1, 2 ) );
cly = New Object( complex( 2, 3 ) );
Show( clx << Add( cly ) );
clx << Delete;
cly << Delete;
Delete Classes( "complex" );Betreff: Übergabe von Nachrichten an „this“ innerhalb der KlassendefinitionIch vergesse immer wieder, dass sich JSL zwar von den Besten leiht (in diesem Fall). Nachrichtenübermittlung im Smalltalk ), fängt es nie ganz das Besondere am Original ein.