С# для 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.

ссылка на оригинал статьи http://habrahabr.ru/post/246265/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *