AS#開発者向けのC#。 パート5:静的クラス、デストラクタ、およびコンストラクタを操作するためのトリック

画像



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の機能を比較します。



 //////// // C# // //////// // Static class public static class MathHelpers { public const double DegreesToRadians = Math.PI / 180.0; public const double RadiansToDegrees = 180.0 / Math.PI; public static double ConvertDegreesToRadians(double degrees) { return degrees * DegreesToRadians; } public static double ConvertRadiansToDegrees(double radians) { return radians * RadiansToDegrees; } } // Class with a destructor class TemporaryFile { public String Path { get; private set; } TemporaryFile(String path) { Path = path; File.Create(path); } // Destructor ~TemporaryFile() { File.Delete(Path); } } // Class with shared constructor code class Vector3 { double X; double Y; double Z; Vector3() : this(0, 0, 0) { } // shared constructor code Vector3(double x, double y, double z) { X = x; Y = y; Z = z; } Vector3(Vector3 vec) : this(vec.X, vec.Y, vec.Z) { } }
      
      





 ///////// // AS3 // ///////// // Static class - runtime only public class MathHelpers { public static const DegreesToRadians:Number = Math.PI / 180.0; public static const RadiansToDegrees:Number = 180.0 / Math.PI; public function MathHelpers() { throw new Error("MathHelpers is static"); } public static function ConvertDegreesToRadians(degrees:Number): Number { return degrees * DegreesToRadians; } public static function ConvertRadiansToDegrees(radians:Number): Number { return radians * RadiansToDegrees; } } // Class with a destructor 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); } // Destructor - must be called manually function dispose(): void { _file.deleteFile(); } } // Class with shared constructor code class Vector3 { var x:Number; var y:Number; var z:Number; function Vector3() { init(0, 0, 0); } static function fromComponents(x:Number, y:Number, z:Number) { var ret:Vector3 = new Vector3(); ret.init(x, y, z); return ret; } static function fromVector(Vector3 vec) { var ret:Vector3 = new Vector3(); ret.init(vec.X, vec.Y, vec.Z); return ret; } // shared constructor code - helper function required function init(x:Number, y:Number, z:Number): void { this.x = x; this.y = y; this.z = z; } }
      
      








All Articles