AS3からC#への記事の翻訳、パート5:静的クラス、デストラクタ、およびコンストラクタトリック
前回抽象クラスを調べましたが、今週はさらに抽象クラス(抽象クラスよりも)の抽象クラスである静的クラスについて説明します。 また、「デストラクタ」としてよく知られているC#の反コンストラクタについても見ていきます。また、すべてに加えて、クラスコンストラクタを操作する際の面白いトリックも見ていきます。
静的クラス
今日の記事は、「さらに抽象的な」クラスである静的クラスから始めましょう。 抽象クラスを使用する場合、それらを拡張して子クラスをインスタンス化できます。
abstract class Shape { } class Square : Shape // legal { } new Shape(); // illegal new Square(); // legal
静的クラスを使用する場合、インスタンス化も継承もできません。 そのようなクラスをインスタンス化することはできません。
static class Shape { } class Square : Shape // illegal { } new Shape(); // illegal new Square(); // illegal
しかし、なぜそのようなクラスが必要なのでしょうか? このようなクラスは、静的な関数、フィールド、およびプロパティを保存するのに適した場所です。 また、このようなクラスのインスタンスを作成することはできないため、クラス内の任意のデータ型の非静的フィールドを使用することは禁止されています。 クラスインスタンスのコンストラクタも禁止されています。 クラスは自動的に封印されたクラスと同一視されます。 このようなクラスを使用するかなり一般的な例は、Mathクラスです。 このクラスのインスタンスを作成する必要はほとんどありませんが、内部に多数の便利な静的関数(Absなど)とフィールド(PIなど)が含まれています。 そのようなクラスの実装は次のようになります。
public static class Math { // remember that 'const' is automatically static // also, this would surely have more precision public const double PI = 3.1415926; public static double Abs(double value) { return value >= 0 ? value : -value; } } new Math(); // illegal
AS3では、デフォルトではコンパイル段階で静的クラスはサポートされていませんが、再生段階(実行時)でチェックを使用してこの制限を回避できます。 クラスをfinalとして宣言するだけで、このクラスのコンストラクターで常にエラーがスローされます。
public final class Math { public static const PI:Number = 3.1415926; public function Math() { throw new Error("Math is static"); } public static function abs(value:Number): Number { return value >= 0 ? value : -value; } } new Math(); // legal, but throws an exception
デストラクタ
今日のプログラムの次の項目はデストラクタです。デストラクタは「反コンストラクタ」です。これは、通常のコンストラクタの場合のように、クラスを作成するのではなく、クラスを破壊する責任があるためです。 デストラクタは、オブジェクトが占有しているメモリを解放する直前にガベージコレクタによって呼び出されます。 それらは次のようになります。
class TemporaryFile { ~TemporaryFile() { // cleanup code goes here } }
デストラクタを作成するには、クラス名に〜を追加します。 デストラクタは1つしか存在できず、アクセス修飾子を使用することはできません。 通常、デストラクタを作成する必要はありませんが、クラスを使用した後にリソースをクリアする方法として役立つ場合があります。 次の例では、デストラクタを使用してオペレーティングシステムから一時ファイルを削除しますが、別の場合には削除されません。 GCはこれを行いません。
using System.IO; class TemporaryFile { public String Path { get; private set; } TemporaryFile(String path) { Path = path; File.Create(path); } ~TemporaryFile() { File.Delete(Path); } } // Create the temporary file TemporaryFile temp = new TemporaryFile("/path/to/temp/file"); // ... use the temporary file // Remove the last reference to the TemporaryFile instance // GC will now collect temp, call the destructor, and delete the file temp = null;
この例では、TemporaryFileクラスはクラスインスタンスのコンストラクターにファイルを作成し、クラスインスタンスへの参照がなく、クラスをGCでアセンブルしてメモリを解放する準備ができたときにファイルを削除します。 クラスインスタンスをGCでアセンブルする準備ができたときに呼び出される関数はAS3にはありません。 通常、この動作を実装するには、手動で「疑似デストラクタ」を作成して呼び出す必要があります(通常、破棄または破棄と呼ばれます)。
import flash.filesystem; class TemporaryFile { private var _path:String; public function get path(): String { return _path; } public function set path(p:String): void { _path = p; } private var _file:File; function TemporaryFile(path:String) { _path = path; _file = new File(path); var stream:FileStream = new FileStream(); stream.open(_file, FileMode.WRITE); } function dispose(): void { _file.deleteFile(); } } // Create the temporary file var temp:TemporaryFile = new TemporaryFile("/path/to/temp/file"); // ... use the temporary file // Manually call dispose() to delete the temporary file temp.dispose(); // Remove the last reference to the TemporaryFile instance // GC will now collect temp temp = null;
デザイナーと働くときのコツ
今日の最後のトピックは、デザイナーと協力するときのトリックです。 baseキーワードを使用して基本クラスコンストラクターを呼び出す方法は既にわかっています(AS3でsuperキーワードを使用するのと同様)。
class Polygon { Polygon(int numSides) { } } class Triangle : Polygon { Triangle() : base(3) // call the Polygon constructor { } }
また、「オーバーロード」を使用して複数のコンストラクターを作成する可能性を検討しました。
class Vector3 { double X; double Y; double Z; Vector3() { X = 0; Y = 0; Z = 0; } Vector3(double x, double y, double z) { X = x; Y = y; Z = z; } Vector3(Vector3 vec) { X = vec.X; Y = vec.Y; Z = vec.Z; } } Vector3 v1 = new Vector3(); // (0, 0, 0) Vector3 v2 = new Vector3(1, 2, 3); // (1, 2, 3) Vector3 v3 = new Vector3(v2); // (1, 2, 3)
通常、このメソッドは、コンストラクター内のコードの重複につながります。 しかし、なぜなら 最も一般的な3つのパラメーターを取るコンストラクターバージョンは、他の2人のデザイナーから簡単に呼び出すことができます。
class Vector3 { double X; double Y; double Z; Vector3() : this(0, 0, 0) { } Vector3(double x, double y, double z) { X = x; Y = y; Z = z; } Vector3(Vector3 vec) : this(vec.X, vec.Y, vec.Z) { } } Vector3 v1 = new Vector3(); // (0, 0, 0) Vector3 v2 = new Vector3(1, 2, 3); // (1, 2, 3) Vector3 v3 = new Vector3(v2); // (1, 2, 3)
これを使用して、クラス内の他のコンストラクターを呼び出すことができます(親クラスのコンストラクターを呼び出すことができるbase()に似ています)。 また、AS3にはデフォルトではそのような機能がなかったため、作成されたオブジェクトでinit / setup / contructなどの関数を呼び出す静的擬似コンストラクターを使用して「エミュレート」する必要がありました。
class Vector3 { var x:Number; var y:Number; var z:Number; function Vector3() { init(0, 0, 0); } // pseudo-constructor static function fromComponents(x:Number, y:Number, z:Number) { var ret:Vector3 = new Vector3(); ret.init(x, y, z); return ret; } // pseudo-constructor static function fromVector(Vector3 vec) { var ret:Vector3 = new Vector3(); ret.init(vec.X, vec.Y, vec.Z); return ret; } // helper function function init(x:Number, y:Number, z:Number): void { this.x = x; this.y = y; this.z = z; } } var v1:Vector3 = new Vector3(); // (0, 0, 0) var v2:Vector3 = Vector3.fromComponents(1, 2, 3); // (1, 2, 3) var v3:Vector3 = Vector3.fromVector(v2); // (1, 2, 3)
今日はここで終わります。そして、いつものように、記事の最後で、今日説明したC#とAS3の機能を比較します。
|
|