[Перевод] С# для AS3 разработчиков. Часть 2: Расширение классов и реализация Интерфейсов

imageПеревод статьи From AS3 to C#, Part 2: Extending Classes and Implementing Interfaces

Эта статья продолжает серию «C# для AS3 разработчиков», и сегодня мы рассмотрим устройство классов в C# с точки зрения AS3 разработчика (наследование классов, реализация интерфейсов и наследование интерфейсов).Начнём с наследования классов. Вот, как это выглядит в AS3:

class Shape { } class Circle extends Shape { } А вот, как это выглядить в C#:

class Shape { } class Circle: Shape { } Как вы могли заметить, вместо ключевого слова extends, используется: (двоеточие).

Похожим образом обстоят дела с реализацией интерфейсов. Как это выглядит в AS3:

interface IHasArea { function GetArea (): int; } interface IRound { function GetSmoothness (): int; } class Shape { } class Circle extends Shape implements IHasArea, IRound { function GetArea (): int { return 33; // TODO рассчитать } function GetSmoothness (): int { return 44; // TODO рассчитать } } Та же самая структура кода, но в C#:

interface IHasArea { int GetArea (); } interface IRound { int GetSmoothness (); } class Shape { } class Circle: Shape, IHasArea, IRound { int GetArea () { return 33; // TODO рассчитать } int GetSmoothness () { return 44; // TODO рассчитать } } В С#, двоеточие используется вместо ключевого слова implements, по такому же принципу, как и с extends. Описание интерфейсов в C# похоже на описание оных в AS3.

Пример расширения интерфейсов в AS3:

interface ISuper { } interface ISub extends ISuper { } Скорее всего, вы уже догадываетесь, как этот код выглядит в C#…

interface ISuper { } interface ISub: ISuper { } Давайте разберёмся, как описываются отношения между родительскими и дочерними классами/интерфейсами в C#. В AS3 вы можете использовать ключевые слова this и super в любых не статических функциях, чтобы обратиться к экземпляру текущего класса (this) или к экземпляру родительского класса (super). Например:

class Polygon { var numVertices: uint; function printDescription (): String { return «Polygon (numVertices=» + numVertices + »)»; } } class Triangle extends Polygon { var color: String; var polygonDescriptionAtConstructionTime: String; function Triangle (color: String) { this.color = color; polygonDescriptionAtConstructionTime = super.printDescription (); } function printDescription (): String { return «Triangle (color=» + color + »)»; } } В данном примере, ключевое слово super обращается исключительно к переменным и функциям класса Polygon. Такой способ обращения к функциям используется крайне редко, но иногда он может помочь избежать в коде двусмысленностей, относительно того, какая из функций printDescription будет вызвана. Если бы в данном примере не использовалось слово super, то вызывалась бы функция printDescription класса Triangle, т.к. поиск в текущем классе происходит раньше родительского класса.

Ключевое слово this обращается исключительно к переменным и функциям класса Triangle. В примере, this используется, чтобы компилятор понимал, что нужно обрщаться к переменной color класса Triangle, а не к одноимённой переменной, передаваемой в конструктор.

А теперь версия на C#:

class Polygon { uint NumVertices; String PrintDescription () { return «Polygon (numVertices=» + numVertices + »)»; } } class Triangle: Polygon { String Color; String PolygonDescriptionAtConstructionTime; Triangle (String color) { this.Color = color; PolygonDescriptionAtConstructionTime = base.printDescription (); } String printDescription () { return «Triangle (color=» + color + »)»; } } Эти два примера очень похожи, за исключением того, что в C#, вместо ключевого слова super, используется ключевое слово base. В C# base выполняет те же функции, что и super в AS3.

Другой пример использования super в AS3 (вызов родительского конструктора):

class Polygon { var numVertices: uint; function Polygon (numVertices: uint) { this.numVertices = numVertices; } } class Triangle extends Polygon { var color: String; function Triangle (numVertices: uint, color: String) { super (numVertices); this.color = color; } } C# версия:

class Polygon { uint NumVertices; Polygon (uint numVertices) { NumVertices = numVertices; } } class Triangle: Polygon { String Color; Triangle (uint numVertices, String color) : base (numVertices) { } } Помимо того, что мы снова заменили super на base, вы можете заметить, что вызов происходит до выполнения кода в конструкторе (до фигурных скобок {}). Так же, вызову конструктора родительского класса предшествует двоеточие (:). Обратите внимание, что в конце строки вызова, не ставится точка с запятой (;).

Давайте разберём, как в AS3 сделать так, чтобы класс нельзя было расширить:

final class FinalClass { } // Этот класс не будет компилироваться class DerviedClass extends FinalClass { } Похожий функционал в C#:

sealed class FinalClass { } // Этот класс не будет компилироваться class DerviedClass: FinalClass { } В данном случае различия между C# и AS3 состоят только в названии ключевых слов. В C# класс, котоырй нельзя расширить обозначается ключевым словом sealed, а в AS3 для этого используется final, но эффект — абсолютно одинаковый.

В завершении, сравнение описанных особенностей C# и AS3 кода:

//////// // C# // //////// // Interface interface IShape { String GetDescription (); } // Sub-interface (one that extends another) interface IPolygon: IShape { uint GetNumEdges (); } // Class class Shape { String Name; Shape (String name) { Name = name; } } // Derived class (one that extends another) class Circle: Shape { int Radius; Circle (String name, int radius) : base (name) { Radius = radius; } } // Derived class that also implements an interface class Triangle: Shape, IPolygon { Triangle () : base («Triangle») { } uint GetNumEdges () { return 3; } String GetDescription () { return «A three-sided polygon»; } } // Class that can’t be extended sealed class NoDerivatives { } ///////// // AS3 // ///////// // Interface interface IShape { function getDescription (): String; } // Sub-interface (one that extends another) interface IPolygon extends IShape { function getNumEdges (): uint; } // Class class Shape { var name: String; function Shape (name: String) { this.name = name; } } // Derived class (one that extends another) class Circle extends Shape { var Radius: int; function Circle (name: String, radius: int) { super (name); Radius = radius; } } // Derived class that also implements an interface class Triangle extends Shape implements IPolygon { function Triangle () { super («Triangle»); } function GetNumEdges (): uint { return 3; } function GetDescription (): String { return «A three-sided polygon»; } } // Class that can’t be extended final class NoDerivatives { } На этом мы сегодня закругляемся. В следующей статье мы поговорим о геттерах и сеттерах (getter/setter) и закончим описание основ классов. После чего, мы сможем перейти к нюансам C#, аналогов которых нет в AS3.

© Habrahabr.ru