Extending Array in Actionscript 3 (Flex)

2020-06-04 02:14发布

问题:

I'm trying to make a variation on Array for a very specific purpose. When I have the following:

public class TileArray extends Array {
   // Intentionally empty - I get the error regardless
}

Why can't I do this?

var tl:TileArray = [1,2,3];

despite the fact that I can do this

var ar:Array = [1,2,3];

The error I receive is this:

Implicit coercion of a value with static type Array to a possibly unrelated type

回答1:

Instead of extending Array you could write your own class that exposes all the methods of Array. By employing the Proxy class you can redirect all default Array methods to an internal array but still have the flexibility to add your own methods:

package
{
    import flash.utils.flash_proxy;
    import flash.utils.Proxy;

    use namespace flash_proxy;

    dynamic public class ExampleArray extends Proxy
    {
        private var _array:Array;

        public function ExampleArray(...parameters)
        {
            _array = parameters;
        }

        override flash_proxy function callProperty( name:*, ...rest):* 
        {
            return _array[name].apply(_array, rest);

        }

        override flash_proxy function getProperty(name:*):* 
        {
            return _array[name];
        }

        override flash_proxy function setProperty(name:*, value:*):void 
        {
            _array[name] = value;
        }

        public function getSmallestElement():*
        {
            var helper:Array = _array.concat().sort();
            return helper[0];
        }

    }
}

example:

var test:ExampleArray = new ExampleArray(8,7,6,5,4,3,2,1);
trace( test.getSmallestElement()); // 1
test.sort();
trace(test); // 1,2,3,4,5,6,7,8 


回答2:

[] only creates an Array. It cannot be used to create a subclass of Array.

The good way to "extend" Array with new functionality is to write standalone utility functions that manipulate regular Arrays. Best of all, this will allow you to do anything to any Array and not be limited only to Arrays created using your subclass.

Here's a simple example of a class that contains utility functions for Arrays:

package com.example.utils
{
    public class ArrayUtil
    {
        public static function traceArray( array:Array ):void
        {
            trace( array.length, "[" + array + "]" );
        }
    }
}

Usage:

ArrayUtil.traceArray( [1, 2, 3] ); //output: 3 [1,2,3]


回答3:

[1,2,3] is shorthand (or syntactic sugar) for new Array(1,2,3). With that in mind, it seems more apparent why your code fails.

Every TileArray is an Array, since TileArray extends Array, but the inverse is not true: not every Array is a TileArray. So, you can't pass an Array where a TileArray is expected. That's why you get the compiler error.

Casting will only defer the error from compile-time to run-time, since the actual type of your object is Array, which is indeed unrelated to TileArray.

If you want to extend Array functionality (and also be able to add some syntactic sugar), you might want to look into extending Proxy, as it was already suggested. Keep in mind it's less performant, so if you plan to use this class heavily, this might not be the best idea.