Действительно ли законно расширить класс Класса?

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

VerifyError: Error #1107: The ABC data is corrupt, attempt to read out of bounds.

То, что я задаюсь вопросом, - то, если разделение на подклассы Класса даже возможно, если бы существует, возможно, некоторый случай, где выполнение этого было бы соответствующим, и не только грубое неправильное употребление ООП. Я полагаю, что это должно быть возможно, поскольку ActionScript позволяет Вам создавать переменные Типа класса. Это использование описано в записи LiveDocs для Класса, все же я не видел упоминаний о разделении на подклассы Класса.

Вот псевдопример кода:

class Foo extends Class

var A:Foo = new Foo(); // A is a class
trace(A is Class); // true, right?
var b = new A(); // b is an instance of class A

Я понятия не имею что тип b был бы. Это было бы это?

trace(b is A); // true?

Но затем, мог Вы вводить переменную b вводить A, как в var b:A = new A();, даже при том, что A не существует до времени выполнения? Я считал, что это не возможно как A не статически разрешимо, но я делаю свои собственные тесты для исследования этой возможности.

В конечном счете цель состоит в том, чтобы генерировать новые классы во времени выполнения, и затем создать экземпляры тех классов.

Таким образом: можно ли разделить класс Класса на подклассы? Если так, как можно сделать это без ошибок, и какой тип экземпляры экземпляры подкласса Класса?

5
задан ivanreese 10 April 2010 в 21:04
поделиться

2 ответа

Вот результаты моего собственного глубокого исследования:

Расширение класса Class кажется по сути невозможным, хотя нигде из того, что я видел, это плохо документировано. По результатам моего исследования я теперь убежден, что сам класс Class не включает в себя все качества, которые есть у других классов верхнего уровня, хотя все они, как говорят, являются наследниками класса Object.

Еще одно разочарование вызывает тот факт, что создание подклассов различных классов верхнего уровня приведет к появлению нескольких различных сообщений об ошибках, что несколько затруднит определение проблем, связанных с игрой. Начнем с простого примера. Если вы попытаетесь создать подкласс многих примитивных типов данных ActionScript (int, uint, Number, String, Boolean и т. Д.), Вы получите следующую ошибку компилятора :

1016: Base class is final.

Это имеет смысл , потому что просмотр документации для любого из этих классов показывает, что они действительно являются final:

Package       Top Level
Class         public final class Boolean
Inheritance   Boolean -> Object

Ключевое слово final, конечно, означает, что другой класс не может расширять класс, помеченный как final . Теперь, чтобы получить более сложный пример, давайте рассмотрим расширение класса Function. Согласно документации, класс Function не является окончательным.Поскольку это не окончательный вариант, означает ли это, что мы можем расширить класс Function для создания наших собственных специализированных функциональных объектов? Вот определение:

class MyFunction extends Function { /*...*/ }

.. а затем во время выполнения :

VerifyError: Error #1103: Class ::MyFunction cannot extend final base class.

Сравните это с примитивной ошибкой типа данных выше. Эта ошибка произошла во время компиляции, поскольку унаследованный примитивный класс был фактически помечен как окончательный. Класс Function не помечен как окончательный, но класс по-прежнему ведет себя так, как если бы он был, только во время выполнения.

Теперь мы подошли к главному вопросу: расширение класса Class. Как и в случае с классом Function, класс Class не является окончательным. Кроме того, класс Class является динамическим, что означает, что новые свойства могут быть добавлены к объекту Class во время выполнения.

В качестве интересного примечания: класс Function также является динамическим, и я считаю, что это часть того, что позволяет продолжать поддерживать старые прототипные механизмы наследования, присутствующие в диалекте ECMAscript. На этом диалекте функции используются как своего рода классы (ну, прототипы), а возможность добавления свойств во время выполнения является частью возможностей прототипного наследования.

Насколько я понимаю, свойства объекта Class такие же, как статические свойства, доступные для любого экземпляра этого класса. Таким образом, должно иметь логический смысл, что кто-то может пожелать манипулировать объектом Class во время выполнения, позволяя им изменять поведение этого класса и его экземпляров. То, что класс Class является динамическим, подкрепляет это понятие.

Поскольку класс Class не является окончательным, мне было любопытно посмотреть, можно ли расширить класс Class, чтобы создать свою собственную специализацию модели Class и работать где-нибудь в области метаязыка. Я оставлю на другой день обсуждение того, почему кто-то захочет это сделать и какую мощность это гипотетически позволит. Теперь, что касается заключительного примера, давайте расширим класс Class. Вот определение:

// the definition causes no errors on its own, even though the compiler "sees" it
class MyClass extends Class { /*...*/ }

/* elsewhere */

MyClass; // the only mention of MyClass beyond the definition

.. а затем во время выполнения :

verify global$init()
                    stack:
                    scope: 
                     locals: global 

/* snip about 120 lines */

   46:getlex 34
                    stack: global Class$?
                    scope: global Object$ Class$ 
                     locals: global 
   48:newclass MyClass$cinit()
VerifyError: Error #1107: The ABC data is corrupt, attempt to read out of bounds.

    at global$init()

Holy stacktrace! Ошибка VerifyError зарезервирована для искаженных данных SWF. Судя по тому, что я смог найти, именно так обычно проявляется «ошибка» во Flash Player. В любом случае это немного выходит за рамки обычной ошибки ActionScript.

На этом этапе становится довольно сложно понять, что именно происходит, но это то, что я смог сделать до сих пор.

VerifyError: Error #1107: The ABC data is corrupt, attempt to read out of bounds.

Я (ошибочно, см. Комментарий ниже) считаю, что «ABC» означает абстрактный базовый класс, который является термином, применяемым к классам, которые не могут быть созданы, а только расширены. Однако указанная выше ужасающая ошибка возникает не при создании экземпляра, а при первом обращении к подклассу MyClass Class. Фактически, в коде примера я ни разу не создаю экземпляр объекта MyClass, я имею в виду только сам класс MyClass.

Я провел еще несколько тестов и обнаружил, что у объектов класса нет конструкторов, по крайней мере, тех, которые обычно происходят из подклассов объектов. Просто набрав new Class (); в любом месте вашего кода, вы наглядно продемонстрируете этот факт, но вы можете исследовать это дальше, изучив .constructor и другие уловки. В результате этого экземпляры класса Class в лучшем случае являются объектами второго класса, поскольку они не могут быть созданы во время выполнения.

Сначала я подозревал, что это была точная причина моей неприятной VerifyError . Однако теперь я считаю, что в классе есть много других элементов,невидимый для нашего собственного кода ActionScript, который может существовать или не существовать в классе Class, классе Function или в других любопытных местах. Конечно, когда Flash Player пытается получить доступ к одному из тех, которые необходимы для расширения базового класса, а он не существует (поскольку класс, возможно, является ABC, таким образом, отсутствуют определенные элементы, присутствующие в нормальном классе), вполне можно ожидать чтобы увидеть выход за пределы VerifyError .

Таким образом, расширение класса Class в настоящее время кажется невозможным. Казалось бы, класс Class не включает в себя все качества, которые большинство других классов верхнего уровня наследуют от Object, хотя это сложно проверить.

Я бы предпочел видеть более конкретное сообщение об ошибке в результате расширения Class, но на данный момент такого нет. Мне бы хотелось, чтобы в ActionScript вернулись некоторые возможности метапрограммирования. На данный момент достаточно точно знать, что это невозможно сделать, по крайней мере, таким образом.

1
ответ дан 14 December 2019 в 13:31
поделиться

В первом абзаце сказано: Каждый объект Class является экземпляром класса Class. Следовательно, расширение класса будет ошибкой, поскольку любой объект класса уже является классом.

Вы сказали о системе, которая генерирует некоторые шаблоны, а затем генерирует некоторые объекты на основе этих шаблонов. Похоже, вы действительно пытаетесь создать интерфейс.

Интерфейс следует использовать, когда ваш шаблон не предоставляет никакой реализации. То есть вы объявляете набор полей и методов, но не предоставляете реализацию методов. Вы должны объявить такой класс следующим образом:

public interface Foo {
    function bar:void;
}

Теперь, чтобы создать класс, реализующий этот интерфейс, вы просто выполните следующее .

public class MyClass implements Foo {
    function bar:void {
        ..... implementation goes here .....
    }
}

Класс может реализовывать несколько интерфейсов, в то время как он может расширять только один класс.

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

Надеюсь, это поможет.

5
ответ дан 14 December 2019 в 13:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: