поиск

Переопределение методов с неограниченным числом параметров

Намусорил: Юрий «Бармалей» Яровой
В категории: ActionScript 3

Это очень короткий пост о том, как в подклассе переопределить метод надкласса, принимающий неограниченное количество параметров.

Предположим, у нас есть класс Foo, в котором объявлен метод bar, принимающий один фиксированный параметр str, а так же произвольное число дополнительных параметров:

Actionscript:
  1. package 
  2. {
  3.      public class Foo
  4.      {
  5.           public function Foo()
  6.           {
  7.                
  8.           }
  9.  
  10.           public function bar(str:String, ...rect):void
  11.           {
  12.                trace("STR: " + str);
  13.                for(var i:int = 0; i <rect.length; i ++)
  14.                {
  15.                     trace(rect[i]);
  16.                }
  17.           }
  18.      }
  19. }

И есть его подкласс SubFoo, в котором мы хотим переопределить метод bar. Это делается следующим образом:

Actionscript:
  1. package 
  2. {
  3.      public class SubFoo extends Foo
  4.      {
  5.           public function SubFoo()
  6.           {
  7.                
  8.           }
  9.          
  10.           override public function bar(str:String, ...rect):void
  11.           {
  12.                // Подготавливаем массив всех параметров.
  13.                rect.unshift(str);
  14.                // Вызываем метод bar суперкласса через apply,
  15.                // передавая ему массив всех параметров.
  16.                super.bar.apply(this, rect);
  17.                
  18.                // Выполняем какие-то дополнительные действия...
  19.           }
  20.      }
  21. }

Тестируем:

Actionscript:
  1. package
  2. {
  3.      import flash.display.Sprite;
  4.      
  5.      public class Main extends Sprite
  6.      {
  7.           public function Main():void
  8.           {
  9.                var foo:SubFoo = new SubFoo();
  10.                foo.bar("hello", 10, false);
  11.           }
  12.      }
  13. }

Если вам известны более элегантные способы решения данной задачи, то не стесняйтесь выкладывать их в комментариях к этой записи. =)



Kомментариев - 17 к «Переопределение методов с неограниченным числом параметров»

Santer [30 января, 2008 в 11:12]

Интересное решение и очень элегантное :)

Kradar [30 января, 2008 в 12:36]

ИМХО, подкласс - класс, определяемый внутри другого класса. А вот термина "надкласс" я вообще не встречал.

В данном случае, мне кажется, корректнее прозвучат термины "родитель" и "потомок".

Юрий Яровой [30 января, 2008 в 13:35]

Почему же? «Надкласс» — достаточно устоявшийся термин и встречается в литературе довольно часто. Так же как и «суперкласс». А вот термины «родитель» и «потомок» уместнее все же применять к элементам составной структуры вроде узлов XML-дерева или элементов DisplayList-а в AS3.

Andy One [30 января, 2008 в 14:35]

Могу предложить обойтись от строчки rect.unshift(str);
Я пишу обычно вот так: super.bar.apply(this, [str].concat(rect));, но тут мы теряем малую часть читабельности кода.

Kradar [30 января, 2008 в 14:39]

Просто если "подкласс" - класс, определяемый внутри другого класса, то "надкласс", по идее, должен быть классом, внутри которого определен "подкласс". И тут уже возможна путаница.

Юрий Яровой [31 января, 2008 в 02:15]

Ну что уж тут поделаешь? Таковы правила разговорной речи. Термин имеет место быть и из языка его уже не выкинешь. Меня вот например с детства поражал следующий факт: почему пододеяльник называется пододеяльником, если одевается НА одеяло. ;-)

k0zer [31 января, 2008 в 17:51]

наверное потому что изначально имел вид простынки, которая клалась ПОД одеало ))

Paul [1 февраля, 2008 в 15:50]

Наверное, потому что предназначается 'под' одеяло. :)

xxax [6 февраля, 2008 в 21:38]

Прикольно получаеся что любой подкласс превратить в класс со моножеством функций.

Козерог [6 февраля, 2008 в 21:49]

Можно по другому сделать

Юрий Яровой [7 февраля, 2008 в 04:40]

Козерог, как?

sliders [8 февраля, 2008 в 16:06]

Да неплохой метод, по другому может и возможно, но зачем?) Я думаю легче не будет)

dsfgdsgf [8 февраля, 2008 в 16:09]

Мне кажеться метод очень хороший. Подругому конечно можно сделать, но лучше врятли получится.

Stanny [10 февраля, 2008 в 01:35]

сломал моск если чесно

black [13 февраля, 2008 в 05:35]

Может я чего-то не понимаю, но что вам не понравилось в таком коде:

Actionscript:
  1. package  {
  2.  
  3.     public class A {
  4.         public function foo (s : String, ...rest):void {
  5.             trace ("A:foo (s="+s+", rest="+rest+")");
  6.         }
  7.     }
  8.    
  9. }
  10.  
  11. package  {
  12.  
  13.     public class B extends A {
  14.         override public function foo (s : String, ...rest):void {
  15.             super.foo (s, rest);
  16.             trace ("B:foo (s="+s+", rest="+rest+")");
  17.         }
  18.     }
  19.    
  20.    
  21. }
  22.  
  23. package  {
  24.     import flash.display.MovieClip;
  25.    
  26.     public class MainCode extends MovieClip{
  27.        
  28.         public function MainCode() {
  29.             var a:A = new A ();
  30.             var b:B = new B ();
  31.             a.foo ("vasya", 1, 2, 3, 4, 5);
  32.             b.foo ("vasya", 1, 2, 3, 4 ,5);
  33.         }
  34.        
  35.     }
  36.    
  37. }

И результат вызова будет таким:

Actionscript:
  1. A:foo (s=vasya, rest=1,2,3,4,5)
  2. A:foo (s=vasya, rest=1,2,3,4,5)
  3. B:foo (s=vasya, rest=1,2,3,4,5)

black [13 февраля, 2008 в 16:14]

Я понял в чем была моя ошибка: при работе с varargs-методами слабый момент в том,
как выполнить представление параметров для ...параметра, в случае если фактический аргумент является массивом:

Actionscript:
  1. public function bar (...rest):void {
  2.    trace ("A:bar length=" + rest.length + "; rest=" + rest);
  3.    for (var i : int = 0; i &lt;rest.length; i++ ) {
  4.     trace ("rest[" + i + "] is " + (typeof rest[i]) + " = " + rest[i]);
  5.     for (var j:Object in rest[i])
  6.       trace ("rest["+i+"]["+j+"] = "+ rest[i][j]);
  7.    }
  8. }

И при использовании:

Actionscript:
  1. a.bar (1, 2, 3);
  2. a.bar ([1,2,3]);

Результаты будут:

Actionscript:
  1. A:bar length=3; rest=1,2,3
  2. rest[0] is number = 1
  3. rest[1] is number = 2
  4. rest[2] is number = 3
  5. A:bar length=1; rest=1,2,3
  6. rest[0] is object = 1,2,3
  7. rest[0][0] = 1
  8. rest[0][1] = 2
  9. rest[0][2] = 3

Даже если параметр один и он является массивом, то он будет передан "без развертывания", по сути упакован внутрь еще одного массива и передан
как его первый и единственный элемент.

Я просто перенес свой опыт в java, там идеология другая: если параметр один и он массив, то он будет передан без лишней "упаковки".
В приниципе, это удобно: ведь выполнить дополнительную упаковку параметров не состовляет сложностей, а вот распаковать их сложно и здесь нужны конструкции уровня языка (тот же apply)

JAVA:
  1. public class TestVargs {
  2.     public static void bar (Object ...rest){
  3.         System.out.printf("TestCargs:bar (rest.length=%d, rest=%s)\n", rest.length, Arrays.deepToString(rest));
  4.     }
  5.  
  6.     public static void main(String[] args) {
  7.         TestVargs.bar (1,2,3);
  8.         TestVargs.bar (new Object [] {1,2,3});
  9.         TestVargs.bar (new Object [] {1,2,3}, new Object [] {4,5,6});
  10.     }
  11. }

И результат будет таким:

JAVA:
  1. TestCargs:bar (rest.length=3, rest=[1, 2, 3])
  2. TestCargs:bar (rest.length=3, rest=[1, 2, 3])
  3. TestCargs:bar (rest.length=2, rest=[[1, 2, 3], [4, 5, 6]])

В AS-примере я был введен в заблуждение результатом вывода

Actionscript:
  1. trace ("B:foo (s="+s+", rest ="+rest+")");

Результаты вывода абсолютно идентичны в случае, когда rest является [1,2,3,4,5] и в случае [[1,2],[3,4],5].

Если здесь есть адепты других языков, то интересно было бы послушать как принято это решение там?

Двина [10 апреля, 2008 в 22:50]

Много лишнего. Но идея сама по себе рентабильна.

Написать комментарий:

 

Bы можете использовать следующие теги для форматирования: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>



User's collector

Внимание!
Эта опция станет доступной только после того как вы авторизуетесь.


 запомнить меня 
Я новый пользователь

На правах рекламы