Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Отсутствие доступа к защищённому свойству суперкласса (http://www.flasher.ru/forum/showthread.php?t=169972)

dump13 15.10.2011 21:09

Отсутствие доступа к защищённому свойству суперкласса
 
Вложений: 1
Здравствуйте,
непонятная проблема с защищённым свойством. Есть два класса: ColorMatrix и его наследник ColorMatrixInterpolator. У родительского ColorMatrix есть protected-свойство _data:
Код AS3:

public class ColorMatrix {
        protected var _isDirty:Boolean;
        protected var _doConstrain:Boolean;
        protected var _data:Array;
        // ...
}

Наследник ColorMatrixInterpolator в конструкторе делает так:
Код AS3:

public function ColorMatrixInterpolator (matrix0:ColorMatrix, matrix1:ColorMatrix, indices:Vector.<int> = null) {
        _m0 = matrix0;
        _m1 = matrix1;
        _indices = indices? copyIndices (indices) : new Vector.<int> ();
        _t = 0;
        super (matrix0._data, false);
}

где _m0 - экземпляр ColorMatrix. Пробую компилировать - кидается исключение
Цитата:

Attempted access of inaccessible property _data through a reference with static type gamma.helpers:ColorMatrix.
Делаю _data пабликом - всё работает.
Подумал, может дело в SDK или FlashDevelop - юзаю последние релизные версии. Или всё-таки моя ошибка?
Если не лень, посмотрите плиз во вложениях.

goodguy 15.10.2011 21:12

Цитата:

matrix0._data
Если свойство протектед, то оно доступно только потомкам класса и самому экземпляру класса.
Так что нужно вызывать его либо:
Код AS3:

this._data

либо просто
Код AS3:

_data

А в данном случае не удивительно, что нет доступа к защищенному свойству другого экземпляра. Все логично. Тут уж только паблик.

dump13 15.10.2011 21:21

Сорри, я забыл написать, что
Код AS3:

public class ColorMatrixInterpolator extends ColorMatrix {/*...*/}

вернее, я написал это
Цитата:

два класса: ColorMatrix и его наследник ColorMatrixInterpolator
но в глаза не бросается :)
В общем, совсем непонятно, что за хрень. Не попробуете скомпилировать пример у себя?

Bgg 15.10.2011 21:26

Цитата:

Сообщение от dump13 (Сообщение 1039460)
Подумал, может дело в SDK или FlashDevelop - юзаю последние релизные версии.

Полезнее думать после чтения справки: Атрибуты свойств классов

Код AS3:

matrix0._data

Вы обращаетесь к свойству, которое закрыто для внешнего использования.

goodguy 15.10.2011 21:32

Цитата:

Сорри, я забыл написать, что
Я это понял.
Свойство _data будет доступно самому экземпляру.
Но в данном случае matrix0 - это уже другой экземпляр, пусть даже того же класса.
У других экземпляров будет доступ только к его public свойствам

dump13 15.10.2011 21:36

Ну хорошо, давайте так, я приведу здесь оба этих класса, чтобы всем было видно, что второй класс унаследован от первого.
Код AS3:

package gamma.helpers {
        import flash.filters.ColorMatrixFilter;
        /**
        * Матрица, используемая при создании фильтра ColorMatrixFilter.
        * @author dump13
        */

        public class ColorMatrix {
                protected var _isDirty:Boolean;
                protected var _doConstrain:Boolean;
                protected var _data:Array;
 
                public function ColorMatrix (data:Array = null, doConstrain:Boolean = false) {
                        if (data) {
                                _data = copyData (data);
                                _isDirty = true;
                        }
                        else {
                                reset ();
                        }
                        _doConstrain = doConstrain;
                }
 
                public function clone ():ColorMatrix {
                        return new ColorMatrix (_data, _doConstrain);
                }
 
                private function copyData (array:Array):Array {
                        var res:Array = [];
                        var na:int = array.length;
                        for (var n:int = 0; n < na; n++) {
                                res.push (array[n]);
                        }
                        return res;
                }
 
                public function reset ():void {
                        _data = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0];
                        _isDirty = true;
                }
 
                // ************************* SET METHODS **************************
 
                /// Устанавливает "сырые" значения матрицы.
                public function setRawData (array:Array):void {
                        if (array.length != 20) {
                                throw new Error ("Неверная длина массива (должна быть равна 20).");
                        }
                        _data = copyData (array);
                        _isDirty = true;
                }
 
                /// Устанавливает оффсет-значения (смещения) для четырёх каналов.
                public function setOffsets (red:int = 0, green:int = 0, blue:int = 0, alpha:int = 0):void {
                        _data[4] = red;
                        _data[9] = green;
                        _data[14] = blue;
                        _data[19] = alpha;
                        _isDirty = true;
                }
 
                /// Устанавливает цветовой баланс - множители главной диагонали матрицы для четырёх каналов.
                public function setBalance (red:Number = 1, green:Number = 1, blue:Number = 1, alpha:Number = 1):void {
                        _data[0] = red;
                        _data[6] = green;
                        _data[12] = blue;
                        _data[18] = alpha;
                        _isDirty = true;
                }
 
                /// Устанавливает смещения цветовых каналов (R, G, B) в значение offset.
                public function setRGBOffset (offset:int):void {
                        _data[4] = offset;
                        _data[9] = offset;
                        _data[14] = offset;
                        _isDirty = true;
                }
 
                /// Устанавливает множители для цветовых каналов (R, G, B) в значение mult.
                public function setRGBMult (mult:Number):void {
                        _data[0] = mult;
                        _data[6] = mult;
                        _data[12] = mult;
                        _isDirty = true;
                }
 
                // ************************* CONCAT METHODS ******************************
 
                /// Прибавляет указанные оффсет-значения (смещения) к соответствующим значениям четырёх каналов.
                public function addOffsets (red:int = 0, green:int = 0, blue:int = 0, alpha:int = 0):void {
                        _data[4] += red;
                        _data[9] += green;
                        _data[14] += blue;
                        _data[19] += alpha;
                        _isDirty = true;
                }
 
                /// Объединяет переданный цветовой баланс с текущим - умножает значения главной диагонали четырёх каналов на указанные величины.
                public function concatBalance (red:Number = 1, green:Number = 1, blue:Number = 1, alpha:Number = 1):void {
                        _data[0] *= red;
                        _data[6] *= green;
                        _data[12] *= blue;
                        _data[18] *= alpha;
                        _isDirty = true;
                }
 
                /// Прибавляет указанные значение offset к смещениям цветовых каналов (R, G, B).
                public function addRGBOffset (offset:int):void {
                        _data[4] += offset;
                        _data[9] += offset;
                        _data[14] += offset;
                        _isDirty = true;
                }
 
                // *********************** OTHER METHODS **************************
 
                /// Создаёт и возвращает новый ColorMatrixFilter, основанный на состоянии текущей матрицы ColorMatrix. Флаг isDirty сбрасывается в false.
                public function getFilter ():ColorMatrixFilter {
                        if (_isDirty) {
                                _isDirty = false;
                                if (_doConstrain) constrainAll ();
                        }
                        return new ColorMatrixFilter (_data);
                }
 
                /// Ограничивает смещения четырёх каналов границами [-255, 255].
                public function constrainAll ():void {
                        constrainOffset (4);
                        constrainOffset (9);
                        constrainOffset (14);
                        constrainOffset (19);
                        _isDirty = true;
                }
 
                /// Ограничивает значение смещения канала границами [-255, 255].
                /// @param index Индекс канала. Допустимые значения: 4, 9, 14, 19.
                private function constrainOffset (index:int):void {
                        var curval:int = _data[index];
                        if (curval < -255) {
                                _data[index] = -255;
                                return;
                        }
                        if (curval > 255) _data[index] = 255;
                }
 
                // ACCESSORS
 
                /// Была ли текущая матрица изменена. Сбрасывается в false каждый раз при вызове getFilter().
                public function get isDirty ():Boolean { return _isDirty; }
 
                /// Следует ли ограничивать оффсет-значения (смещения) при генерации фильтра. Значение по умолчанию - false.
                public function get doConstrain ():Boolean { return _doConstrain; }
                public function set doConstrain (value:Boolean):void {
                        _doConstrain = value;
                }
 
        }
 
}

А теперь второй класс. Это - наследник первого класса.
Код AS3:

package gamma.helpers {
        import flash.filters.ColorMatrixFilter;
        /**
        * Интерполятор содержит ссылки на две матрицы - _m0 и _m1. В векторе _indices содержатся индексы тех значений, которые необходимо интерполировать (предполагается, что значения с другими индексами в обеих матрицах совпадают). При изменении параметра t интерполятор помечается как неактуальный (_isDirty = true). При вызове getFilter() неактуальный интерполятор производит обновление своих значений, а затем уже возвращает фильтр.
        * @author dump13
        */

        public class ColorMatrixInterpolator extends ColorMatrix {
                protected var _m0:ColorMatrix;
                protected var _m1:ColorMatrix;
                protected var _indices:Vector.<int>;
                protected var _t:Number;
 
                /// Конструктор интерполятора цветовых матриц. Интерполятор устанавливает свои "сырые" значения в значения матрицы matrix0.
                /// @param matrix0 Первая матрица, соответствующая начальному состоянию интерполятора.
                /// @param matrix1 Вторая матрица, соответствующая конечному состоянию интерполятора.
                /// @param indices Вектор индексов тех значений, которые будут изменяться в процессе интерполяции. Все остальные значения будут оставаться равными соответствующим значениям из матрицы matrix0.
                public function ColorMatrixInterpolator (matrix0:ColorMatrix, matrix1:ColorMatrix, indices:Vector.<int> = null) {
                        //super ();
                        _m0 = matrix0;
                        _m1 = matrix1;
                        _indices = indices? copyIndices (indices) : new Vector.<int> ();
                        _t = 0;
                        super (matrix0._data, false);
                }
 
                override public function clone ():ColorMatrix {
                        var ip:ColorMatrixInterpolator = new ColorMatrixInterpolator (_m0, _m1, _indices);
                        ip._t = _t;
                        return ColorMatrix (ip);
                }
 
                private function copyIndices (vec:Vector.<int>):Vector.<int> {
                        var res:Vector.<int> = new Vector.<int> ();
                        var na:int = vec.length;
                        for (var n:int = 0; n < na; n++) {
                                res.push (vec[n]);
                        }
                        return res;
                }
 
                override public function getFilter ():ColorMatrixFilter {
                        if (_isDirty) {
                                _isDirty = false;
                                interpolate ();
                        }
                        return new ColorMatrixFilter (_data);
                }
 
                /// Обновляет состояние интерполятора.
                private function interpolate ():void {
                        var na:int = _indices.length;
                        for (var n:int = 0; n < na; n++) {
                                var index:int = _indices[n];
                                _data[index] = GMath.interpolateLinear (_m0._data[index], _m1._data[index], _t);
                        }
                }
 
                // ********************** INDICES SETTING **************************
                // Методы из этого раздела не проверяют наличие других добавленных индексов, т.е. если добавить один и тот же индекс в вектор indices несколько раз, интерполяция также будет осуществляться повторно.
 
                /// Заставляет интерполировать все значения матрицы.
                public function setAllIndices ():void { for (var n:int = 0; n < 19; n++) { _indices.push (n); } }
 
                /// Заставляет интерполировать множители цветовых каналов (на главной диагонали).
                public function addRGBMultIndices ():void { _indices.push (0, 6, 12); }
 
                /// Заставляет интерполировать множители, лежащие на диагонали.
                public function addRGBAMultIndices ():void { _indices.push (0, 6, 12, 18); }
 
                /// Заставляет интерполировать смещения цветовых каналов.
                public function addRGBOffsetIndices ():void { _indices.push (4, 9, 14); }
 
                /// Заставляет интерполировать смещения всех каналов.
                public function addRGBAOffsetIndices ():void { _indices.push (4, 9, 14, 19); }
 
                // ACCESSORS
 
                /// Матрица, соответствующая начальному состоянию интерполятора. Аксессоры производят её клонирование.
                public function get matrix0 ():ColorMatrix { return _m0.clone (); }
                public function set matrix0 (value:ColorMatrix):void {
                        _m0 = value.clone ();
                        _isDirty = true;
                }
 
                /// Матрица, соответствующая конечному состоянию интерполятора. Аксессоры производят её клонирование.
                public function get matrix1 ():ColorMatrix { return _m1.clone (); }
                public function set matrix1 (value:ColorMatrix):void {
                        _m1 = value.clone ();
                        _isDirty = true;
                }
 
                /// Индексы значений, которые будут изменяться в процессе интерполяции.
                public function get indices ():Vector.<int> { return _indices; }
                public function set indices (value:Vector.<int>):void {
                        _indices = copyIndices (value);
                }
 
                /// Параметр, по которому производится интерполяция (от нуля до единицы).
                public function get t ():Number { return _t; }
                public function set t (value:Number):void {
                        _t = value;
                        _isDirty = true;
                }
 
                override public function set doConstrain (value:Boolean):void {
                        throw new Error ("Запрещено изменять doConstrain интерполятора.");
                }
 
        }
 
}

А теперь объясните плиз, почему свойство с атрибутом protected, который, как написано по ссылке выше,
Цитата:

Видимый для ссылок в том же классе и в производных классах
не видно в производном классе?

dump13 15.10.2011 21:40

Хм... Ну вот, пока писал, человек мне уже доступно объяснил :)
Всё, вопросов нет, спасибо.

in4core 15.10.2011 21:40

Вам уже все обяъяснили зрите в корень :
Код AS3:

  protected var _m0:ColorMatrix;

Это значит вы создли переменную типа protected и хотите у этой переменной схавать
Код AS3:

super (matrix0._data

свойство дата которое тоже протектед. На глаз это сразу не видно но если подумать....
Вот пример того что вы делаете
Код AS3:

class A
protected var b:int = 55;
 
var a:A = new A();
trace(a.b) // WTF ?


wvxvw 16.10.2011 11:47

Вместо того, чтобы заигрывать с суперконструктором, лучше написать статический метод-фабрику, в нем, кстати, и protected свойства доступны будут.

dump13 16.10.2011 12:55

Блин, я совсем запутался. Из этого примера просто стало понятно, что вот в таком случае протектед использовать не получится, а почему этого делать нельзя - непонятно. Помогите разобраться, например здесь доступ к _ownVar другого экземпляра работает и я всегда этим пользовался:
Код AS3:

package gamma.tests {
 
        public class A {
                protected var _ownVar:int;
 
                public function A (ownVar:int) {
                        _ownVar = ownVar;
                }
 
                public function equals (a:A):Boolean {
                        return _ownVar == a._ownVar;
                }
 
        }
 
}

То есть a в методе equals() - это уже другой экземпляр, но того же класса. Когда я в первый раз это проверил, я решил, что, раз уж _ownVar может быть доступно в каком-нибудь подклассе, то тот подкласс сможет таким же образом рыться в других экземплярах. А сейчас не могу понять, почему не может.

Цитата:

Сообщение от wvxvw
написать статический метод-фабрику, в нем, кстати, и protected свойства доступны будут

можно ссылку или пример?

Upd: wvxvw, всё, понял о чём речь.


Часовой пояс GMT +4, время: 20:50.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.