Подтвердить что ты не робот

Правильное использование тезисов

Только вчера я решил начать изучать язык программирования Haxe после того, как использовал ActionScript 3 в течение последних нескольких лет. Сегодня я изучаю абстрактные типы, и я понял, что они кажутся совершенно отличными от абстрактных классов на Java. Я начинаю понимать, что они делают, но я не уверен, для чего используются тезисы. Что представляет собой правильное использование тезисов в Haxe, и когда я должен одобрять их по классам?

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

abstract Complex({real:Float, imag:Float}) {
    public function new(real:Float, imag:Float) {
        this = { real: real, imag: imag };
    }

    public function real():Float {  return this.real; }
    public function imag():Float {  return this.imag; }

    @:op(A + B)
    public static function add(lhs:Complex, rhs:Complex):Complex {
        return new Complex(lhs.real() + rhs.real(), lhs.imag() + rhs.imag());
    }

    public function toString():String {
        return real() + " + " + imag() + "i";
    }
}
4b9b3361

Ответ 1

Действительно, абстракты совсем не похожи на абстрактные классы в Java. Абстрактные типы в Haxe являются мощными и интересными. Их главная характеристика заключается в том, что они являются типами, которые существуют только во время компиляции. Во время выполнения они полностью заменяются завернутым типом. Методы преобразуются в статические функции. В случае, когда вы описали все ваши экземпляры, будут заменены анонимными объектами с двумя полями real и imag. Это хороший прецедент? Вероятно, да, поскольку тип Complex не предназначен для расширения, и вы, вероятно, хотите определить некоторую перегрузку оператора (как и для добавления).

Чтобы сделать его еще более легким, вы можете использовать Array<Float> в качестве обернутого типа, где первым элементом является действительная часть, а вторая - мнимая.

Так что же хорошего в абстрактных типах?

  • они добавляют семантические типы (особенно примитивные типы). Например, вы можете определить abstract RGB(Int) {}, чтобы всегда выводить очень эффективную цветовую кодировку с выгодой для методов и свойств. Или у вас может быть abstract Path(String) {}, чтобы иметь дело с конкатенацией путей, относительными путями и т.п.
  • вы можете определить перегрузку оператора. В приведенном выше примере вы можете сделать что-то вроде white + black и получить от него что-то значимое.
  • аналогично перегрузке оператора, тезисы могут определять неявные отбрасывания от и к другим типам. В случае с RGB выше вы можете легко определить метод fromString() для разбора шестнадцатеричной строки в Int, представляющей цвет. С неявным броском вы можете сделать: var color : RGB = "#669900";. thx.color определяет множество рефератов для обработки цветов.
  • они идеально подходят для обертывания очень мощных Enums в Haxe. С абстрактным вы можете добавлять методы и свойства к перечислениям (которые изначально не поддерживают ни одно из них).
  • они идеально подходят для упаковки оптимизированного кода. Абстрактные методы могут быть встроены, и завернутый тип гарантирует, что вы не добавляете дополнительный слой косвенности при выполнении кода.

Что не так хорошо? Или лучше, что мы должны знать о рефератах?

  • поскольку они всего лишь артефакт времени компиляции, вы не можете использовать проверки выполнения (например: no Std.is(value, MyAbstract)).
  • тезисы не являются классами, поэтому нет наследования.