以下はほとんど正しいです。何かを見逃していたり、何かを誤解していたりする可能性があります。リンクされたドキュメント (短すぎます) を読んで、コメント欄に書き込んでください。ありがとうございます。
悪いたとえ: クラスはクッキー カッターです。 インスタンスは、クッキーの抜き型で作られたクッキーです。
類推の問題:JSLにも電話するつもりですクラスあるプロトタイプ。 プロトタイプは実際のクッキーです。 原型のクッキーできる食べたり改変したりすることはできますが、通常はそうしたくないでしょう。 代わりに、クッキー生地の輪郭をトレースし、それをハサミで切って、新しいクッキーのインスタンスを作成する必要があります。 ただし、プロトタイプの Cookie を噛むと、将来のすべての Cookie インスタンスも噛まれたように見えます (2 番目の例)。 また、プロトタイプ Cookie に対して _init_(...) メソッドが実行されていないため、中途半端かもしれませんが、正しい形になっています。
のドキュメンテーション用途レンプレートそれよりもプロトタイプ。 私はテンプレートよりもプロトタイプを好みます。プロトタイプは使用可能なオブジェクトですが、テンプレートはスプレー ペイントをどこに配置するかを示すだけです。 この微妙な違いは、最初の例では重要ではありません。
簡単な例
これは単純な単一クラスの例です。バブル。 クラスのプロトタイプは DefineClass() によって作成されます。 NewObject() はプロトタイプからの 61 個の実際のインスタンス。 61 個のインスタンスにはそれぞれ半径と X、Y 中心があります。 プロトタイプは、_init_(...)、drift()、draw() へのメソッドも提供します。 オブジェクトを使用してグラフを表示します各オブジェクトのdrawメソッド。 次に、ループが実行され、各オブジェクトのオブジェクト ドリフト メソッドが呼び出され、グラフに再描画が指示されます。 結果は次のようなアニメーション化されたグラフになります。
グラフの JSL:
// define a simple class (like a template) to represent a 2D bubble
Define Class("bubble",
// class member variables
m_radius = .; // class member variables are specified in
m_xpos = .; // the class definition with initial values.
m_ypos = .; // these values are copied into instances created by NewObject(...)
// class methods
_init_ = Method( {radius, x, y}, // called by NewObject(bubble(r,x,y)) below to initialize an instance
this:m_xpos = x; // this: is the namespace of an instance
m_ypos = y; // you don't need "this:" unless the member name is
m_radius = radius; // the same as a parameter name
);
drift = Method( {}, // a method to move the bubble
m_xpos = m_xpos * 0.995;// tentatively drift to center
m_ypos = m_ypos * 0.995;
);
draw = Method( {}, // a method to draw the bubble
Circle( {m_xpos, m_ypos}, m_radius )
);
);
// make a bunch of instances of the bubble class, keep them in a list
bubblelist = {};
For( i = 1, i <= 61, i += 1,
Insert Into( bubblelist,
// each instance of bubble is initialized with a random radius and position
New Object( bubble( Random Uniform( .03, .8 ), Random Uniform( -.9, .9 ), Random Uniform( -.9, .9 ) ) )
)
);
picno = 0; // need an ID for each picture
// make a window to display all the instances of the bubble class
New Window( "bubble class instances",
gb = Graph Box( // the graphic script for the graph box scales and sizes the axes and...
xaxis( {Add Ref Line( 0, "Solid", "Black", "", 1 )} ),
yaxis( {Add Ref Line( 0, "Solid", "Black", "", 1 )} ),
framesize( 600, 600 ),
X Scale( -1, 1 ),
Y Scale( -1, 1 ),
// the graphic script tells each bubble to draw itself
For( i = 1, i <= N Items( bubblelist ), i += 1,
bubblelist[i]:draw()
);
text({-.9,-.9},char(picno)),
<<ONCLOSE></ONCLOSE>それがどのように機能するかについての私のメンタル モデル: DefineClass() は、内部ですべての DefineClass() プロトタイプの非表示リストを保持しています。多くのインスタンスのようなもの。 それについては後ほど詳しく説明します。上の例では、NewObject() 関数を通じてそれらにアクセスします。 NewObject() は、プロトタイプ オブジェクトの新しいインスタンスを複製し、_init_ メソッドを実行します。
なに?これ: ?
上の例では、メンバー変数に次の名前を付けました。 m_接頭辞。 これは必須ではありませんが、どの変数がメンバー変数であるかを覚えておくことと、パラメーター名やローカル変数名の衝突を防ぐことの両方に役立ちます。 でも私も使ってましたこれ:m_xpos _init_() メソッドの割り当ての 1 つで。 のこれ:名前空間は「現在のインスタンスのメンバー変数」を意味します。 それでこれ:x = x;メンバー変数 x とパラメーター x を同じ名前にしたい場合に使用できます。 m_次にコードを保守する人にとって、より簡単になります。
なに?バブル: ?
別の名前空間がありますほとんど必要のないものこれは、私が非表示リストの DefineClass() プロトタイプが見えると言った理由を示しています。多くのインスタンスと同様 -- クラス名は名前空間。 使用するバブル:m_radiusインスタンス メソッドからもプロトタイプの m_radius にアクセスします。 静的メンバー変数が必要だと思われる場合は、注意すれば、これを作成する方法があります。
静的な値のプロトタイプの使用
次の例では、静的な m_ID 変数を使用します。 コメントが示唆するように、おそらく別のバリエーションを作成する必要がありましたが、これは「注意していれば」という警告を説明しているため、依然として役に立ちます。 何が起こるかは次のとおりです (私のメンタル モデルをもう一度)。
以下の _init_() が実行されると、 bubble2 クラスはすべてのプロトタイプのコンテンツを新しいインスタンスにコピーしています。 新しいインスタンスには、プロトタイプの m_id のコピーが含まれます。 次に、_init_() はプロトタイプ内の m_id() を変更します。 次のインスタンスは変更された値を取得します。 他のメンバー関数は、プロトタイプの m_id (bubble2:m_id) と this:m_id (または名前空間のない単に m_id) のどちらかを選択する必要があります。 ここでは、インスタンスに固有の整数のコピーである m_id を使用します。
ビデオでは、パズルの最後のピースが画面の下端の 5:15 の位置に収まります。 黒丸は、m_id 値を表示している bubble2 です。 彼らは m_id を使用して、すべての近隣を調査するときに自分自身を無視するようにします。
// twist is a scaling divisor for a shearing rotation that moves
// the outer edge faster.
// this value needs to get bigger with more beehive cells.
global:twist = 600;
// choose the size to make them fit, but it also interacts with twist
// because the distance from the center grows
global:bubblesize = 0.057;
// use a defined class to represent each cell in the beehive.
Define Class("bubble2",
m_radius = .; // in the video, all beehive cells have the same radius
m_xpos = .; // the beehive cell's position
m_ypos = .;
//
// this is answering the question "can a JSL Class have a static member variable?"
// this could have been done more intuitively for this example by passing the
// index of the creation loop to the _init_ code, but here it is...initialize the
// "static" value to 1...
m_id = 1; // keep reading to understand the two-faced nature of this variable...
// What actually happens: when newObject(bubble2(...)) makes a new instance, the _init_(...)
// is called.
// First, the m_id is cloned from the prototype to the instance. The first instance gets m_id==1.
// Second, the bubble2: namespace causes the prototype class to increment the
// prototype's m_id. The next instance gets the new value from the prototype, m_id==2.
// this is a little odd, coming from a C++ -like language; in the drift method below,
// "other:m_id != m_id" both m_id values are regular non-static instance members.
// if you want the static behaviour, use the bubble2:m_id approach (bubble2 is the class
// name and access the singleton in the prototype class.)
// Normally you *never* want to use the class name as a name space qualifier because
// you set up the class correctly and initialize via _init_( parameters ). And normally
// a static value is also a constant value, so using a copy is just fine. But if
// multiple instances need to communicate via a singleton static, AND you always use
// the namespace, this is a reasonable place to keep the static.
// Having written all that, I now dislike this particular example because it is using
// a confusing combination of bubble2:m_id and instance values of m_id.
_init_ = Method( {radius, x, y},
m_radius = radius;
this:m_xpos = x; // this: (or nothing) operates on an instance
m_ypos = y;
bubble2:m_id++; // bubble2: operates on the prototype. The next newobject(bubble2(...)) uses the modified prototype
);
distanceBetweenCenters = Method( {other},
/*return*/ Sqrt( (m_xpos - other:m_xpos) ^ 2 + (m_ypos - other:m_ypos) ^ 2 )
);
distanceBetweenEdges = Method( {other}, // negative: overlaps
/*return*/ distanceBetweenCenters( other ) - (m_radius + other:m_radius)
);
drift = Method( {},
// bubbles should pull to 0,0 AND move away from near bubbles
angle = ATan( m_ypos, m_xpos );
radius = Sqrt( m_ypos ^ 2 + m_xpos ^ 2 );
shear = global:twist; // also depends on number of circles
shrink = .99950;
// radius/shear creates a tiny amount of rotation, more on the edges. That rotational
// shearing helps the circles bounce about. /400 is not enough and /100 is too much.
// radius*shrink pulls all the circles to the origin. It is balanced by push, below.
x = Cos( angle + radius / shear ) * radius * shrink;
y = Sin( angle + radius / shear ) * radius * shrink;
// check neighbors
{neighbors, distances} = kdt << kNearestRows( 7, m_id );
tension = 0;
ntension = 0; // calculate a tension, or stress, for contour to use as a color
For( iN = 1, iN <= N Items( neighbors ), iN += 1,
i = neighbors[iN];
other = bubblelist[i];
If( other:m_id != m_id, // <<<<<<<<<<<<<<<< NOT the bubble2:m_id value !!!
dist = distanceBetweenEdges( other );
// if the dist is zero, it is perfect. if the other guy is far away, ignore him.
If( Abs( dist ) < global:bubblesize * 0.8,
tension += dist ^ 2; // this will be a RMS value at the bottom
ntension += 1;
);
If( dist < 0, //push
angle = ATan( m_ypos - other:m_ypos, m_xpos - other:m_xpos );
x += Cos( angle ) * Abs( dist ) ^ .4 * .05;
y += Sin( angle ) * Abs( dist ) ^ .4 * .05;
);//
, //
Beep()
);
);
m_xpos = x;
m_ypos = y;
If( ntension == 0,
ntension = 1;
tension += (global:bubblesize / 2) ^ 2;
);
Sqrt( tension / ntension ); // RMS
);
draw = Method( {},
Transparency( .8 );
Circle( {m_xpos, m_ypos}, m_radius, "FILL" );
Transparency( 1 );
Text( center justified, {m_xpos, m_ypos - m_radius * .2}, Char( m_id ) );
);
);
bubblelist = {};
n = 12; // how many "rings" of hex cells
m = -26 + 21 * n + 3 * (n - 3) ^ 2; // yes, I used JMP to get this formula
For( i = 1, i <= m, i += 1,
Insert Into(
bubblelist,
New Object( bubble2( Random Uniform( global:bubblesize, global:bubblesize ), Random Uniform( -.9, .9 ), Random Uniform( -.9, .9 ) ) )
)
);
// need a table for contour plot, and it will include 100 values in a circle around the hive
ring = 100;
dt = New Table( "tension",
Add Rows( m + ring ),
New Column( "x", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [] ) ),
New Column( "y", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [] ) ),
New Column( "tension", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [] ) )
);
For( i = 1, i <= ring, i += 1,
angle = 2 * Pi() * i / ring;
dt:x[m + i] = 1.25 * Sin( angle );
dt:y[m + i] = 1.25 * Cos( angle );
dt:tension[m + i] = 0;
);
cplot = dt << Contour Plot(
X( :x, :y ),
Y( :tension ),
Show Data Points( 0 ),
Fill Areas( 1 ),
Label Contours( 0 ),
Transform( "Range Normalized" ),
Color Theme( "Green Yellow Red" ),
Specify Contours( Min( 0 ), Max( .01 ), N( 50 ) )
);
Report( cplot )[framebox( 1 )] << Frame Size( 1920, 1080 ) << maximizewindow( 1 ) << backgroundcolor( "black" );
Report( cplot )[framebox( 1 )] << xaxis(
{Format( "Fixed Dec", 12, 3 ), Min( -1.4*1920/1080 ), Max( 1.4*1920/1080 ), Inc( 0.5 ), Label Row(
{Show Major Grid( 0 ), Show Major Labels( 0 ), Show Major Ticks( 0 ), Show Minor Grid( 0 ), Show Minor Labels( 0 ), Show Minor Ticks( 0 )}
)}
);
Report( cplot )[framebox( 1 )] << yaxis(
{Format( "Fixed Dec", 12, 3 ), Min( -1.4 ), Max( 1.4 ), Inc( 0.5 ), Label Row(
{Show Major Grid( 0 ), Show Major Labels( 0 ), Show Major Ticks( 0 ), Show Minor Grid( 0 ), Show Minor Labels( 0 ), Show Minor Ticks( 0 )}
)}
);
// here is the script that makes the bubbles draw
Report( cplot )[framebox( 1 )] << addgraphicsscript(
Fill Color( "black" );
text Color( "white" );
pen Color( rgbcolor(64,64,64) );
For( i = 1, i <= N Items( bubblelist ), i += 1,
bubblelist[i]:draw()
);
hline(0);
vline(0);
);
cplot << onclose(
keepRunning = 0;
Close( dt, nosave );
1;
);
Wait( 0 );
//dir = "$temp\ClassWithStatic" || Char( global:twist ) || "\";
//Delete Directory( dir );
//Create Directory( dir );
//Write( Convert File Path( dir, "windows" ) );
picno = 0;
keepRunning = 1;
While( keepRunning,
xy = J( N Items( bubblelist ), 2, . );
For( i = 1, i <= N Items( bubblelist ), i += 1,
xy[i, 1] = bubblelist[i]:m_xpos;
xy[i, 2] = bubblelist[i]:m_ypos;
);
// the kdtable makes it faster to find near neighbors
kdt = KDTable( xy );
For( i = 1, i <= N Items( bubblelist ), i += 1,
dt:tension[i] = bubblelist[i]:drift();
dt:x[i] = bubblelist[i]:m_xpos;
dt:y[i] = bubblelist[i]:m_ypos;
);
Report( cplot )[framebox( 1 )] << inval << updatewindow;
picno += 1;
// Report( cplot )[framebox( 1 )] << save picture( dir || Char( (picno) + 1e6 ) || ".png" );
Wait( .01 );
);
上記の両方の例は、オブジェクトを表すデータ テーブルの行とメソッドのメンバー変数と JSL ユーザー関数を表す列を使用して、同様に簡単に (おそらく簡単に) 構築できます。 特にサブクラス化を行わずにクラスを使用すると、JSL のクラスに慣れていない他の人が JSL を理解するのが難しくなる可能性があります。
関数について言えば、DefineClass のドキュメントでも言及されています。 私の知る限り、それらはテーブルにほとんど何ももたらさないので、おそらく避けるべきです。 おそらく、クラスのすべてのインスタンスが、すべてのメソッドとすべてのメンバー変数の個別のコピーを取得していると思います。 Function() を定義してメンバー変数に格納すると、(おそらく) 1 つのコピーだけでよりグローバルな名前空間に存在できるものをコピーする別のものを作成していることになります。 しかし、インスタンスが 1 つだけ (または非常に少数) で、パラメーター以外は何も認識しないクラスの関数が本当に必要な場合は、クラス内の関数が必要になる可能性があります。
最後の例に進み、サブクラス化を行って最後の名前空間を見てみましょう。素晴らしい: 、私はそれを探す必要がありました(JSLのコメントを参照)。
直感的な例: 基本クラスは車両、サブクラス (または派生クラス) はトラックと乗用車です。 トラックは、基本クラスのナビゲーション方法を、住宅街を避けることを認識している方法に置き換える可能性があります。 車はHOVレーンを利用するかもしれません。 車両のリストは、A から B に移動するように指示されたときに、それぞれ正しい動作をします。
「クラスの定義」には興味深い議論があります。基本クラス(...) 。 以下の例では、形が基本クラスとなり、四角と丸形状から導き出されます。 この例では、四角形と円のリストを作成して表示します。
two squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filledtwo squares, two circles, two outlined, two filled2 つの正方形、2 つの円、2 つの輪郭、2 つの塗りつぶし
以下の説明は試行錯誤に基づいています。何かがどのように機能するかを予測するのに役立つモデルとして十分に正しいと私は信じています。
なに?素晴らしい: ?
派生クラスが作成されると、JMP はクラスの最後まで実行されます。基本クラスチェーンして先頭に戻り、最初に基本クラスを独自の名前空間に作成します。 名前空間は内部で相互にリンクされているため、派生クラスは独自の名前空間を検索し、変数が見つかるまで名前空間チェーンを基底クラスまでたどることでメンバー変数を参照できます。 の素晴らしい: 名前空間は、現在の名前空間を調べずに名前空間チェーンを 1 回前方にスキップすることを意味します。 これが、以下の JSL が「必要がない場合は基本メソッドを呼び出すために super: を使用しないでください」と言っている理由です。基本メソッドは派生名前空間にアクセスできないため、派生関数を呼び出すことができません。
多重継承: 「インターフェイス」を使用し、重複した名前を避けている場合は、機能する可能性があります。 幸運を。 上記のモデルの名前空間のチェーンのどこに兄弟基本クラスが収まるのかわかりません。
// demonstrates JMP class inheritance and overriding a method
// and calling the super class. A circle and a square class
// are derived from a shape class. Explains when to NOT use super:.
//
// I found super: in https://github.com/sassoftware/jsl-hamcrest/blob/master/Source/Core/Matchers/EqualTo.jsl
// it isn't documented anywhere else, but works great for calling base class _init_
// Also, https://github.com/sassoftware/jsl-hamcrest/blob/master/Source/Core/Utils.jsl
// shows a "self" implementation idea. This is a bad idea because it creates a circular reference
// that must be cleared before the object is lost/deleted...or it will leak.
// avoid making members and methods in base and derived classes with the same name.
// _init_, _to string_, _show_ are exceptions, but they must not try to use a derived
// class member or method. (you would not normally want to, so no problem.)
//
// avoid needless upcast (super:); it cripples the base class because there is no downcast or
// virtual mechanism. Without the upcast, a baseclass function runs with access to the
// derived class members and methods. (see square's draw method calling docolor calling record.)
//
// it appears that the derived chain is searched *after* the current class; in a two class
// (base,derived) example that inverts the search order for members and methods when a
// derived class uses "super:" to call a base class method. If the base class calls a "virtual"
// function that exists in both base and derived, it won't get the derived one if "super:" was
// used but will if no scope is used. You only need "super:" typically when you want to call
// the base class method from an overridden method of the same name. If the base class method
// isn't calling back to derived via a virtual, everything is good.
// deep details
//
// the output shows lines like this:
// record square=square(shape=(s= x=30 y=30 r=5 s=4 c=yellow f=1))
// record circle=circle(shape=(s= x=30 y=60 r=10 s=99 c=green f=0))
//
// the square and the circle both get the right answer via different
// paths. Because of way draw() is overridden by square and not by circle,
// the initial call, objects[window:i] << draw(), is calling either a
// derived member or a base member. In both cases, "this" is for the
// derived member. in square's draw(), I made an error, now commented
// out: /*super:*/docolor(), that caused docolor to run with "this"
// for the base class, not the derived class. docolor then calls record().
// all three classes have record() members. The intent is to override the
// base class version ("never seen"). The error caused the base class
// version to run for square because "this" of docolor() was for the base class.
Define Class( "shape", // base class for both shapes
m_Xcenter = .;
m_Ycenter = .;
m_radius = .;
m_sides = .;
m_color = .;
m_filled = .;
_init_ = Method( {x, y, radius, sides, color, fill},
m_Xcenter = x;
m_Ycenter = y;
m_radius = radius;
m_sides = sides;
m_color = color;
m_filled = fill;
);
_to string_ = Method( {},
"shape=(s=" ||
" x=" || Char( m_Xcenter ) || " y=" || Char( m_Ycenter ) ||
" r=" || Char( m_radius ) || " s=" || Char( m_sides ) ||
" c=" || Char( m_color ) || " f=" || Char( m_filled ) || ")"
);
_show_ = _to string_;
// the following should NOT ever get called because square and circle override it
// try changing square to call super:docolor and then you'll see this
record=method({},show("never seen, overridden by square and circle"));
// both shapes understand filled vs outlined
// see note in square:draw method about calling docolor without super:
docolor = Method( {},
this:record(); // this: doesn't change anything,
If( this:m_filled, // it is mostly for disambiguating
Fill Color( /*this:*/m_color );// parameter of same name
, //
Pen Color( this:m_color )
)
);
// the base class has a draw method that circle uses;
// square provides an override because this draws a
// diamond-oriented square
draw = Method( {},
docolor();
p = J( m_sides, 3, 2 );//2==draw
p[1, 3] = 1;//1==move
p[m_sides, 3] = -2;//-2==draw and close
For( i = 1, i <= m_sides, i += 1,
p[i, 1] = m_Xcenter + m_radius * Cos( 2 * Pi() * i / m_sides );
p[i, 2] = m_Ycenter + m_radius * Sin( 2 * Pi() * i / m_sides );
);
Path( p, m_filled );
);
);
Define Class( "circle", baseclass( shape ),
_init_ = Method( {x, y, radius, color, fill},
super:_init_( x, y, radius, 99/*sides*/, color, fill )
);
_to string_ = Method( {},
"circle(" || super:_tostring_() || ")"
);
_show_ = _to string_;
record=method({},write("\!nrecord circle=",_show_()));
// circle has no override for draw()
);
Define Class( "square", baseclass( shape ),
_init_ = Method( {x, y, radius, color, fill},
super:_init_( x, y, radius, 4/*sides*/, color, fill )
);
_to string_ = Method( {},
"square(" || super:_tostring_() || ")"
);
_show_ = _to string_;
record=method({},write("\!nrecord square=",_show_()));
// square overrides the base class draw
draw = Method( {},
/*super:*/docolor();// don't up-cast, docolor can't down-cast and gets base class record()
Rect(
m_Xcenter - m_radius,
m_Ycenter - m_radius,
m_Xcenter + m_radius,
m_Ycenter + m_radius,
m_filled
);
);
);
objects = {};
Insert Into( objects, New Object( square( 30, 30, 5, "yellow", 1 ) ) );
Insert Into( objects, New Object( Circle( 30, 60, 10, "green", 0 ) ) );
Insert Into( objects, New Object( square( 60, 30, 15, "blue", 0 ) ) );
Insert Into( objects, New Object( Circle( 60, 60, 20, "red", 1 ) ) );
New Window( "objects",
gb = Graph Box( framesize( 500, 500 ),
For( window:i = 1, window:i <= N Items( objects ), window:i += 1,
//Show( objects[i] );
objects[window:i] << draw(); // uses the base class or the derived class draw
)
)
);
//stop();
// animate the color of object 4, the big red circle
For( i = 0, i <= 1, i += (1 / 256), //show(i);
objects[4]:m_color = HLS Color( i, .5, 1 );
gb << inval << updatewindow;
Wait( 0 );
);
どうですかこれ?
C++ には、オブジェクトがそれ自体を参照するために必要な「this」という名前の値があります (他の言語では「self」と「me」が使用されます)。 これと同じではありません: 名前空間プレフィックス。 JSL クラスはクラス内に「this」を提供していないと思うので、次のようなものを作成したくなるかもしれません。
x = newObject(myClass(17));
x::self = x;
またはそれに近いもの。 次に、myClass メソッドは「self」を使用して、クローン作成などのクラス インスタンスを必要とする処理を行うことができます。
Scripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceScripting index showing messages that can be sent to a class instanceクラスインスタンスに送信できるメッセージを示すスクリプトインデックス
クラス インスタンス (へのポインター) を含むクラス インスタンス内にメンバー変数を保持すると、メモリ リークが発生する可能性があります。 これにより、新しいトピックが登場します...実際にはトピックです。
インスタンスはいつ削除されますか?
インスタンスへの参照がない場合、インスタンスは削除されます。 上のセクションでは、インスタンス内の「self」参照によりインスタンスの削除が防止されます。たとえインスタンスへのハンドルをすべて失ったとしても。 JMP を閉じる以外にクリーンアップする方法はありません。
インスタンスはいつコピーされますか?
ここが最も重要な点です。インスタンスは、<これは、インスタンスが参照によって渡されることを意味します。わーい! JMP に行列引数のコピーをパラメータ値に作成させ、場合によっては別のコピーを返す代わりに、大きな行列をラップしてクラスのインスタンスをユーザー関数に渡す単純なクラスを作成するほうが、はるかに不器用ではありません。