cast()"是做什么的?-6ren"> cast()"是做什么的?-我已经实现了流转换器。请注意,这只是一个练习(为了学习 Dart)。此转换器将整数转换为字符串。我给出下面的代码,你也可以在GitHub上找到它. // Conceptually, a transfo-6ren">
gpt4 book ai didi

stream - Dart "StreamTransformer cast()"是做什么的?

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

我已经实现了流转换器。请注意,这只是一个练习(为了学习 Dart)。此转换器将整数转换为字符串。我给出下面的代码,你也可以在GitHub上找到它.

// Conceptually, a transformer is simply a function from Stream to Stream that
// is encapsulated into a class.
//
// A transformer is made of:
// - A stream controller. The controller provides the "output" stream that will
// receive the transformed values.
// - A "bind()" method. This method is called by the "input" stream "transform"
// method (inputStream.transform(<the stream transformer>).

import 'dart:async';

/// This class defines the implementation of a class that emulates a function
/// that converts a data with a given type (S) into a data with another type (T).
abstract class TypeCaster<S, T> {
T call(S value);
}

/// This class emulates a converter from integers to strings.
class Caster extends TypeCaster<int, String> {
String call(int value) {
return "<${value.toString()}>";
}
}

// StreamTransformer<S, T> is an abstract class. The functions listed below must
// be implemented:
// - Stream<T> bind(Stream<S> stream)
// - StreamTransformer<RS, RT> cast<RS, RT>()

class CasterTransformer<S, T> implements StreamTransformer<S, T> {

StreamController<T> _controller;
bool _cancelOnError;
TypeCaster<S, T> _caster;

// Original (or input) stream.
Stream<S> _stream;

// The stream subscription returned by the call to the function "listen", of
// the original (input) stream (_stream.listen(...)).
StreamSubscription<S> _subscription;

/// Constructor that creates a unicast stream.
/// [caster] An instance of "type caster".
CasterTransformer(TypeCaster<S, T> caster, {
bool sync: false,
bool cancelOnError: true
}) {
_controller = new StreamController<T>(
onListen: _onListen,
onCancel: _onCancel,
onPause: () => _subscription.pause(),
onResume: () => _subscription.resume(),
sync: sync
);
_cancelOnError = cancelOnError;
_caster = caster;
}

/// Constructor that creates a broadcast stream.
/// [caster] An instance of "type caster".
CasterTransformer.broadcast(TypeCaster<S, T> caster, {
bool sync: false,
bool cancelOnError: true
}) {
_cancelOnError = cancelOnError;
_controller = new StreamController<T>.broadcast(
onListen: _onListen,
onCancel: _onCancel,
sync: sync
);
_caster = caster;
}

/// Handler executed whenever a listener subscribes to the controller's stream.
/// Note: when the transformer is applied to the original stream, through call
/// to the method "transform", the method "bind()" is called behind the
/// scenes. The method "bind()" returns the controller stream.
/// When a listener is applied to the controller stream, then this function
/// (that is "_onListen()") will be executed. This function will set the
/// handler ("_onData") that will be executed each time a value appears
/// in the original stream. This handler takes the incoming value, casts
/// it, and inject it to the (controller) output stream.
/// Note: this method is called only once. On the other hand, the method "_onData"
/// is called as many times as there are values to transform.
void _onListen() {
_subscription = _stream.listen(
_onData,
onError: _controller.addError,
onDone: _controller.close,
cancelOnError: _cancelOnError
);
}

/// Handler executed whenever the subscription to the controller's stream is cancelled.
void _onCancel() {
_subscription.cancel();
_subscription = null;
}

/// Handler executed whenever data comes from the original (input) stream.
/// Please note that the transformation takes place here.
/// Note: this method is called as many times as there are values to transform.
void _onData(S data) {
_controller.add(_caster(data));
}

/// This method is called once, when the stream transformer is assigned to the
/// original (input) stream. It returns the stream provided by the controller.
/// Note: here, you can see that the process transforms a value of type
/// S into a value of type T. Thus, it is necessary to provide a function
/// that performs the conversion from type S to type T.
/// Note: the returned stream may accept only one, or more than one, listener.
/// This depends on the method called to instantiate the transformer.
/// * CasterTransformer() => only one listener.
/// * CasterTransformer.broadcast() => one or more listener.
Stream<T> bind(Stream<S> stream) {
_stream = stream;
return _controller.stream;
}

// TODO: what should this method do ? Find the answer.
StreamTransformer<RS, RT> cast<RS, RT>() {
return StreamTransformer<RS, RT>((Stream<RS> stream, bool b) {
// What should we do here ?
});
}
}


main() {

// ---------------------------------------------------------------------------
// TEST: unicast controller.
// ---------------------------------------------------------------------------

// Create a controller that will be used to inject integers into the "input"
// stream.
StreamController<int> controller_unicast = new StreamController<int>();
// Get the stream "to control".
Stream<int> integer_stream_unicast = controller_unicast.stream;
// Apply a transformer on the "input" stream.
// The method "transform" calls the method "bind", which returns the stream that
// receives the transformed values.
Stream<String> string_stream_unicast = integer_stream_unicast.transform(CasterTransformer<int, String>(new Caster()));

string_stream_unicast.listen((data) {
print('String => $data');
});

// Inject integers into the "input" stream.
controller_unicast.add(1);
controller_unicast.add(2);
controller_unicast.add(3);

// ---------------------------------------------------------------------------
// TEST: broadcast controller.
// ---------------------------------------------------------------------------

StreamController<int> controller_broadcast = new StreamController<int>.broadcast();
Stream<int> integer_stream_broadcast = controller_broadcast.stream;
Stream<String> string_stream_broadcast = integer_stream_broadcast.transform(CasterTransformer<int, String>.broadcast(new Caster()));

string_stream_broadcast.listen((data) {
print('Listener 1: String => $data');
});

string_stream_broadcast.listen((data) {
print('Listener 2: String => $data');
});

controller_broadcast.add(1);
controller_broadcast.add(2);
controller_broadcast.add(3);
}

类(class)CasterTransformer<S, T>扩展抽象类 StreamTransformer<S, T> .

因此,它实现了方法StreamTransformer<RS, RT> cast<RS, RT>() .

在文档中,据说:

The resulting transformer will check at run-time that all data events of the stream it transforms are actually instances of S, and it will check that all data events produced by this transformer are actually instances of RT.

参见:https://api.dartlang.org/stable/2.1.0/dart-async/StreamTransformer/cast.html

首先,我认为该文档中有一个拼写错误:它应该说“...它转换实际上是 RS 的实例”(而不是 S)。

然而,这对我来说似乎很模糊。

  • 为什么我们需要流转换器来检查值类型?变压器的目的是转换,不是吗?如果组件的目的是检查,那我们为什么不称它为检查器呢?
  • 另外,为什么我们需要检查转换器(我们实现的)是否生成了所需的数据?如果没有,那么我们将面临一个应该修复的错误。

谁能解释一下这个方法的用途 Cast()

最佳答案

cast方法可以帮助键入操作。

如果你有一个 StreamTransformer<num, int> ,它将数字转换为整数(例如,通过对它们调用 .toInt() 然后加上 42,因为这显然很有用!)。如果您想在某个需要 StreamTransformer<int, num> 的地方使用该变压器,那么你不能。自 num不是 int 的子类型,转换器不可分配给该类型。

但是您知道,因为您了解流转换器的实际工作原理,所以第一个类型参数仅用于输入。接受任何 num 的东西应该可以安全地在只给它的地方使用 int秒。因此,为了让类型系统相信您知道自己在做什么,您可以这样写:

StreamTransformer<int, num> transform = myTranformer.cast<int, num>();

现在,tranformer接受任何整数( RS ),检查它是否为 num ( S ), 传递给 myTransformer这叫toInt()并加 42,然后得到 int ( T ) 传回并且 transformer检查它是 num ( RT ) 并发出它。

一切正常并且类型系统很满意。

您可以使用 cast做一些在运行时永远不会工作的事情,因为它所做的只是添加额外的运行时检查,让静态类型系统相信事情要么会成功,要么会抛出这些检查。

实现 StreamTransformer.cast 的最简单方法是使用 e StreamTransformer.castFrom静态方法:

StreamTransformer<RS, RT> cast<RS, RT>() => StreamTransformer.castFrom(this);

这将在您自己的转换器上使用系统的默认转换包装器。

关于stream - Dart "StreamTransformer<RS, RT> cast<RS, RT>()"是做什么的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53372895/

27 4 0