Методы



Методы — это функции, которые входят в состав определения класса. Когда создается экземпляра класса, с ним связывается метод. В отличие от функции, объявленной за пределами класса, метод нельзя использовать отдельно от экземпляра, с которым он связан.

Методы определяются с использованием ключевого слова function. Как и свойства класса, любой их атрибут можно применить к методам, включая личные, защищенные, общедоступные, внутренние, статические или пользовательские пространства имен. Инструкция function можно использовать следующим образом:

public function sampleFunction():String {}

Также можно использовать переменную, которой присваивается выражение функции, как показано ниже.

public var sampleFunction:Function = function () {}

В большинстве случаев предпочтительнее использовать инструкцию функции, а не выражение, потому что:

  • инструкции функции более точные и простые для чтения;

  • Инструкции функции позволяют использовать ключевые слова override и final. Дополнительные сведения см. в разделе Переопределение методов.

  • Инструкции функции создают более крепкую связь между идентификатором (именем функции) и кодом в теле метода. Так как значение переменной может быть изменено с помощью инструкции присваивания, связь между переменной и ее выражением функции может в любой момент быть разорвана. Хотя это проблему можно обойти, объявив переменную с ключевым словом const вместо var, такой прием лучше не использовать, так как он делает код трудным для чтения и не позволяет использовать ключевые слова override и final.

Единственным случаем, когда необходимо использовать именно выражение функции, является присоединение функции к объекту прототипа. Дополнительные сведения см. в разделе Объект прототипа.

Методы-конструкторы

Методы-конструкторы, иногда их называют простоконструкторами, представляют собой функции с тем же именем, которым назван определяющий их класс. Любой код, включенный в метод-конструктор, выполняется при каждом создании экземпляра класса с использованием ключевого слова new. Например, следующий код определяет простой класс Example, содержащий одно свойство с именем status. Начальное значение переменной status задается в функции конструктора.

class Example 
{ 
    public var status:String; 
    public function Example() 
    { 
        status = "initialized"; 
    } 
} 
 
var myExample:Example = new Example(); 
trace(myExample.status); // output: initialized

Методы-конструкторы могут быть только открытыми, но использование атрибута public является необязательным. Для конструктора нельзя использовать никаких других спецификаторов управления доступом, включая private, protected или internal. Кроме того, с методом-конструктором нельзя использовать пользовательское пространство имен.

Конструктор может явно вызвать конструктор находящегося непосредственно над ним суперкласса с помощью инструкции super(). Если конструктор суперкласса не вызывается явно, компилятор автоматически вставляет вызов перед первой инструкцией в теле конструктора. Также вызывать методы суперкласса можно, используя префикс super в качестве ссылки на суперкласс. Если в теле одного конструктора требуется использовать и конструктор super() и префикс super, первым должен идти конструктор super(). В противном случае ссылка super может повести себя не так, как предполагалось. Конструктор super() также необходимо вызывать перед инструкциями throw или return.

В следующем примере показано, что происходит при попытке использования ссылки super перед вызовом конструктора super(). Новый класс, ExampleEx, расширяет класс Example. Конструктор ExampleEx пытается получить переменную status, определенную в его суперклассе, но делает это перед вызовом super(). Инструкция trace() в конструкторе ExampleEx возвращает значение null, так как переменная status недоступна, пока не будет вызван конструктор super().

class ExampleEx extends Example 
{ 
    public function ExampleEx() 
    { 
        trace(super.status); 
        super(); 
    } 
} 
 
var mySample:ExampleEx = new ExampleEx(); // output: null

Хотя в конструкторе можно использовать инструкцию return, он не может вернуть значение. Другими словами, инструкции return не должны иметь связанных выражений или значений. Соответствующим образом, методы-конструкторы не могут возвращать значения, вследствие чего невозможно указать тип возврата.

Если для класса не определить метод-конструктор, компилятор автоматически создает пустой конструктор. Если данный класс расширяет другой, компилятор включит вызов super() в созданный им конструктор.

Статические методы

Статические методы, также называемые методами класса, — это методы, который объявляются с использованием ключевого слова static. Статические методы, присоединяемые к классу, а не к его экземпляру, полезны для инкапсуляции, которая затрагивает не только состояние отдельного экземпляра. Так как статические методы присоединяются ко всему классу, их можно вызвать только через класс, а через его экземпляр — нет.

Статические методы полезны для инкапсуляции, действие которой не ограничивается состоянием экземпляров класса. Другими словами, метод должен быть статическим, если он обеспечивает функцию, которая не оказывает прямого влияния на значение экземпляра класса. Например, класс Date имеет статический метод parse(), который преобразует строку в число. Это статические метод, так как он не оказывает влияния на отдельные экземпляры класса. Вместо этого, метод parse() берет строку, которая представляет собой значение даты, анализирует ее и возвращает число в формате, совместимом с внутренним представлением объекта Date. Этот метод не является методом экземпляра, так как его бессмысленно применять к одному экземпляру класса Date.

Сравните статический метод parse() с одним из методов экземпляра класса Date, таким как getMonth(). Метод getMonth() является методом экземпляра, так как он воздействует непосредственно на значение экземпляра, получая определенный компонент (месяц) экземпляра Date.

Так как статические методы не связаны с отдельными экземплярами, в их теле нельзя использовать ключевые слова this и super. Ссылки this и super имеют значение, только в контексте метода экземпляра.

В отличие от других языков программирования на базе классов, в ActionScript 3.0 статические методы не наследуются. Дополнительные сведения см. в разделе Статические свойства не наследуются.

Методы экземпляра

Методами экземпляра являются методы, объявленные без ключевого слова static. Методы экземпляра, присоединяемые к экземплярам, а не ко всему классу, полезны для реализации функций, затрагивающих отдельные экземпляры класса. Например, класс Array содержит метод экземпляра sort(), который воздействует непосредственно на экземпляры Array.

В теле метода экземпляра могут содержаться и статические переменные и переменные экземпляра. Это означает, что на переменные, определенные в одном классе, можно ссылаться с использованием простого идентификатора Например, следующий класс, CustomArray, расширяет класс Array. Класс CustomArray определяет статическую переменную arrayCountTotal для отслеживания общего числа экземпляров класса, переменную экземпляра arrayNumber, отслеживающую порядок создания экземпляров, и метод экземпляра getPosition(), возвращающий значения этих переменных.

public class CustomArray extends Array 
{ 
    public static var arrayCountTotal:int = 0; 
    public var arrayNumber:int; 
 
    public function CustomArray() 
    { 
        arrayNumber = ++arrayCountTotal; 
    } 
     
    public function getArrayPosition():String 
    { 
         return ("Array " + arrayNumber + " of " + arrayCountTotal); 
    } 
}

Хотя внешний код должен ссылаться на статическую переменную arrayCountTotal через объект класса с помощью CustomArray.arrayCountTotal, код, находящийся внутри тела метода getPosition(), может ссылаться непосредственно на статическую переменную arrayCountTotal. Это относится даже к статическим переменным суперклассов. Хотя статические свойства не наследуются в ActionScript 3.0, статические свойства суперклассов входят в область действия. Например, класс Array имеет несколько статических переменных, одна из которых является константой с именем DESCENDING. Код, находящийся в подклассе Array, может ссылаться на статическую константу DESCENDING с помощью простого идентификатора:

public class CustomArray extends Array 
{ 
    public function testStatic():void 
    { 
        trace(DESCENDING); // output: 2 
    } 
}

Значением ссылки this в теле метода экземпляра является ссылка на экземпляр, к которому присоединен метод. Следующий код демонстрирует, как ссылка this указывает на экземпляр, содержащий метод.

class ThisTest 
{ 
    function thisValue():ThisTest 
    { 
        return this; 
    } 
} 
 
var myTest:ThisTest = new ThisTest(); 
trace(myTest.thisValue() == myTest); // output: true

Наследованием методов экземпляров можно управлять с помощью ключевых слов override и final. Атрибут override можно использовать для переопределения унаследованного метода, а атрибут final — для запрета переопределения метода подклассами. Дополнительные сведения см. в разделе Переопределение методов.

Методы доступа get и set

Методы доступа get и set, также называемые getter и setter, позволяют соблюдать принципы сокрытия информации и инкапсуляции, обеспечивая простой в использовании интерфейс программирования для создаваемых классов. Функции get и set позволяют делать свойства класса закрытыми, но при этом пользователи класса могут обращаться к этим свойствам так, будто они обращаются к переменной класса, а не вызывают метод класса.

Преимущество такого подхода заключается в том, что он позволяет отказаться от традиционных функций методов доступа с громоздкими именами, такими как getPropertyName() и setPropertyName(). Другое преимущество методов get и set состоит в том, что они позволяют избежать создания двух открытых функций для каждого свойства, разрешающего доступ для чтения и записи.

Следующий пример класса GetSet включает методы доступа get и set с именем publicAccess(), которые обеспечивают доступ к закрытой переменной privateProperty.

class GetSet 
{ 
    private var privateProperty:String; 
     
    public function get publicAccess():String 
    { 
        return privateProperty; 
    } 
     
    public function set publicAccess(setValue:String):void 
    { 
        privateProperty = setValue; 
    } 
}

Если обратиться к свойству privateProperty напрямую, будет выдана ошибка, как показано ниже.

var myGetSet:GetSet = new GetSet(); 
trace(myGetSet.privateProperty); // error occurs

Вместо этого пользователь класса GetSet будет использовать то, что похоже на свойство publicAccess, но на самом деле является парой функций методов доступа get и set, которые воздействуют на закрытое свойство privateProperty. В следующем примере создается экземпляр класса GetSet, а затем задается значение свойства privateProperty с помощью открытого метода доступа publicAccess.

var myGetSet:GetSet = new GetSet(); 
trace(myGetSet.publicAccess); // output: null 
myGetSet.publicAccess = "hello"; 
trace(myGetSet.publicAccess); // output: hello

Функции get и set также позволяют переопределять свойства, унаследованные от суперкласса, что невозможно выполнить при использовании обычных переменных-членов класса. Переменные-члены класса, объявленные с использованием ключевого слова var, не могут переопределяться в подклассе. Однако это ограничение не распространяется на свойства, созданные с помощью функций get и set. Для функций get и set, унаследованных от суперкласса, можно использовать атрибут override.

Связанные методы

Связанный метод, иногда называемый замыканием метода, — это метод, извлеченный из своего экземпляра. К числу связанных методов относятся методы, переданные функции в качестве аргументов или возвращенные функцией в качестве значений. Впервые в ActionScript 3.0 связанные метод уподобляется замыканию функции в том, что он сохраняет всю свою лексическую среду даже при извлечении из экземпляра. Однако между связанным методом и замыканием функции есть важное отличие: ключевое слово this для связанного метода продолжает ссылаться на экземпляр, в котором реализуется метод, то есть остается связанным с ним. Другими словами, ссылка this в связанном методе всегда указывает на исходный объект, в котором определен метод. Для замыканий функций ссылка this является общей, то есть она указывает на любой объект, с которым связана функция в момент вызова.

Важно понимать суть связанных методов, если используется ключевое слово this. Как вы помните, ключевое слово this обеспечивает ссылку на родительский объект метода. Большинство программистов, использующих ActionScript, считают, что ключевое слово this всегда ссылается на объект или класс, содержащий определение метода. Однако это не всегда так, если не применяется связывание метода. Например, в предыдущих версиях ActionScript ключевое слово this не всегда ссылается на экземпляр, в котором реализован метод. Когда методы извлекаются из экземпляра в ActionScript 2.0, ссылка this не связывается с исходным экземпляром, а переменные и методы экземпляра становятся недоступными. В ActionScript 3.0 этого не происходит, так как при передаче методов в качестве параметра автоматически создаются связанные методы. Связанные методы обеспечивают, чтобы ключевое слово this всегда ссылалось на объект или класс, в котором определяется метод.

Следующий код определяет класс ThisTest, который содержит метод foo(), определяющий связанный метод, и метод bar(), возвращающий связанный метод. Внешний код создает экземпляр класса ThisTest, создает метод bar() и сохраняет возвращенное значение в переменной myFunc.

class ThisTest 
{ 
    private var num:Number = 3; 
    function foo():void // bound method defined 
    { 
        trace("foo's this: " + this); 
        trace("num: " + num); 
    } 
    function bar():Function 
    { 
        return foo; // bound method returned 
    } 
} 
 
var myTest:ThisTest = new ThisTest(); 
var myFunc:Function = myTest.bar(); 
trace(this); // output: [object global] 
myFunc(); 
/* output:  
foo's this: [object ThisTest] 
output: num: 3 */

Две последние строки кода показывают, что ссылка this в связанном методе foo() по-прежнему указывает на экземпляр класса ThisTest, несмотря на то, что ссылка this в предшествующей строке указывает на глобальный объект. Более того, связанный метод, сохраненный в переменной myFunc, сохранил доступ к переменным-членам класса ThisTest. Если выполнить этот же код в ActionScript 2.0, ссылки this будут одинаковыми, а переменная num получит значение undefined.

Добавление связанных методов имеет самое большое значение, когда речь идет об обработчиках событий, так как метод addEventListener() требует, чтобы в качестве аргумента передавалась функция или метод. Дополнительные сведения см. в пункте «Функция прослушивателя, определенная в качестве метода класса» раздела Прослушиватели событий.