gpt4 book ai didi

dart - 如何编写抽象类构造函数,以便在子类中灵活扩展

转载 作者:行者123 更新时间:2023-12-03 03:45:37 34 4
gpt4 key购买 nike

我正在尝试实现一个持久的 Stack数据结构。我想将其实现为代数数据类型,因此它有两个具体的子类型:空和非空:

abstract class Stack<T> {
factory Stack.empty() => const _EmptyStack._();

T get data;
Stack<T> get bottom;
bool get isEmpty;
Stack<T> put(T item) => new _StackImpl(item, this);
}

class _StackImpl<T> extends Stack<T> {
final T _data;
final Stack<T> _bottom;

_StackImpl(T this._data, Stack<T> this._bottom);

T get data => _data;
Stack<T> get bottom => _bottom;
bool get isEmpty => false;
}

class _EmptyStack<T> extends Stack<T> {
const _EmptyStack._();
T get data => throw new CollectionIsEmpty();
Stack<T> get bottom => throw new CollectionIsEmpty();
bool get isEmpty => true;
}

此代码在具体实现中引发了两个错误:

[error] The class 'Stack' does not have a default generative constructor

我找到了一个示例代码,似乎 address this problem here ,所以我通过在 Stack<T> 中放置一个无参数构造函数来修复它类(class):

abstract class Stack<T> {
Stack();
// ...

但现在这会导致 _EmptyStack<T> 出现问题构造函数,它是常量:

Constant constructor cannot call non-constant super constructor of 'Stack<T>'

另外添加了 Stack()构造函数阻止将类用作混合。

这些限制似乎迫使类(class)作者考虑如何扩展类(class)。 The way of extending List class来自 dart:collection包似乎证实了这个结论 - 有一个完整的单独类用于扩展,我不能直接扩展 List类本身。

我的问题比上面描述的问题更笼统:我怎样才能编写一个类,以便它可以足够灵活地扩展?这包括允许使用以下功能:
  • 父类(super class)中的工厂构造函数
  • 子类中的普通构造函数
  • const子类中的构造函数
  • 用作混合

  • 虽然我知道作为 mixin 的使用可能是不可能的,甚至是不需要的,但其他点仍然有效。最重要的问题是:为什么我不能 extend带有工厂构造函数的类?这是一种与我熟悉的任何其他 OO 语言不同的行为。

    还有相关问题:
  • Extending a class with only one factory constructor
  • Extending the Exception class in Dart

  • 编辑:感谢 Günter Zöchbauer answer我已经改进了代码,所以现在它可以完全运行了(见下文)。我现在留下的最重要的问题是:为什么工厂构造函数破坏了扩展类的能力?以及如何解决它(除了使用基类作为接口(interface))?一个更简单的例子来说明这一点:

    class Base {
    }

    class _Sub extends Base {
    int someValue;
    _Sub(int this.someValue);
    }

    这段代码一切都很好。但是假设我回到我的 Base及时上课并想添加工厂方法:

    class Base {
    factory Base.empty() => new _Sub(0);
    }

    现在每个扩展 Base 的类因 unresolved implicit call to super constructor 而损坏.那我该怎么办?

    来自原始问题的更正代码以供引用:

    abstract class Stack<T> {
    const Stack._();
    factory Stack.empty() => const _EmptyStack._();

    T get data;
    Stack<T> get bottom;
    bool get isEmpty;
    Stack<T> put(T item) => new _StackImpl(item, this);
    }

    class _StackImpl<T> extends Stack<T> {
    final T _data;
    final Stack<T> _bottom;

    _StackImpl(T this._data, Stack<T> this._bottom) : super._();

    T get data => _data;
    Stack<T> get bottom => _bottom;
    bool get isEmpty => false;
    }

    class _EmptyStack<T> extends Stack<T> {
    const _EmptyStack._() : super._();
    T get data => throw new CollectionIsEmpty();
    Stack<T> get bottom => throw new CollectionIsEmpty();
    bool get isEmpty => true;
    }

    void main(){

    group('stack', (){

    test('empty stack', (){
    var emptyStack = new Stack.empty();
    expect(emptyStack.isEmpty, isTrue);
    expect(() => emptyStack.data, throwsA(new isInstanceOf<CollectionIsEmpty>()));
    expect(() => emptyStack.bottom, throwsA(new isInstanceOf<CollectionIsEmpty>()));

    var emptyStack2 = new Stack.empty();
    expect(emptyStack == emptyStack2, isTrue);
    });

    test('adding to stack', (){

    var stack = new Stack<String>.empty().put("a").put("b").put("c");

    expect(stack.data, equals('c'));
    expect(stack.bottom.data, equals('b'));
    expect(stack.bottom.bottom.data, equals('a'));

    });

    });

    }

    最佳答案

    在您的示例中,我建议仅使用 Stack作为接口(interface)而不是基类。

  • 父类(super class)中的工厂构造函数
    如果你有一个工厂构造函数,如果你想按照链接问题的答案进行扩展,你也必须添加一个普通的构造函数。
  • 子类中的普通构造函数
    这里的实际问题是什么?我猜这和 1 一样。
  • 子类中的 const 构造函数
    如果你想要一个 const 构造函数,所有子类也需要有一个 const 构造函数。
    在具有 const 构造函数的类中,所有字段都必须是 final 的。您的基类不是这种情况,那么将 const 构造函数添加到 _EmptyStack 的意义何在? .
  • 用作mixin
    将类用作 mixin 的限制是暂时的,应该在某个时候删除。
  • 关于dart - 如何编写抽象类构造函数,以便在子类中灵活扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26698982/

    34 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com