Перевод статьи From AS3 to C#, Part 2: Extending Classes and Implementing Interfaces
Эта статья продолжает серию “C# для AS3 разработчиков“, и сегодня мы рассмотрим устройство классов в C# с точки зрения AS3 разработчика (наследование классов, реализация интерфейсов и наследование интерфейсов).
Начнём с наследования классов. Вот, как это выглядит в AS3:
1 2 3 4 5 6 7 8 |
class Shape { } class Circle extends Shape { } |
А вот, как это выглядить в C#:
1 2 3 4 5 6 7 8 |
class Shape { } class Circle : Shape { } |
Как вы могли заметить, вместо ключевого слова extends, используется : (двоеточие).
Похожим образом обстоят дела с реализацией интерфейсов. Как это выглядит в AS3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
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#:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
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:
1 2 3 4 5 6 7 8 |
interface ISuper { } interface ISub extends ISuper { } |
Скорее всего, вы уже догадываетесь, как этот код выглядит в C#…
1 2 3 4 5 6 7 8 |
interface ISuper { } interface ISub : ISuper { } |
Давайте разберёмся, как описываются отношения между родительскими и дочерними классами/интерфейсами в C#. В AS3 вы можете использовать ключевые слова this и super в любых не статических функциях, чтобы обратиться к экземпляру текущего класса (this) или к экземпляру родительского класса (super). Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
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#:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
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 (вызов родительского конструктора):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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# версия:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class Polygon { uint NumVertices; Polygon(uint numVertices) { NumVertices = numVertices; } } class Triangle : Polygon { String Color; Triangle(uint numVertices, String color) : base(numVertices) { } } |
Помимо того, что мы снова заменили super на base, вы можете заметить, что вызов происходит до выполнения кода в конструкторе (до фигурных скобок {}). Так же, вызову конструктора родительского класса предшествует двоеточие (:). Обратите внимание, что в конце строки вызова, не ставится точка с запятой (;).
Давайте разберём, как в AS3 сделать так, чтобы класс нельзя было расширить:
1 2 3 4 5 6 7 8 9 |
final class FinalClass { } // Этот класс не будет компилироваться class DerviedClass extends FinalClass { } |
Похожий функционал в C#:
1 2 3 4 5 6 7 8 9 |
sealed class FinalClass { } // Этот класс не будет компилироваться class DerviedClass : FinalClass { } |
В данном случае различия между C# и AS3 состоят только в названии ключевых слов. В C# класс, котоырй нельзя расширить обозначается ключевым словом sealed, а в AS3 для этого используется final, но эффект – абсолютно одинаковый.
В завершении, сравнение описанных особенностей C# и AS3 кода:
|
|
На этом мы сегодня закругляемся. В следующей статье мы поговорим о геттерах и сеттерах (getter/setter) и закончим описание основ классов. После чего, мы сможем перейти к нюансам C#, аналогов которых нет в AS3.