Index: lib/src/wrappers.dart |
diff --git a/lib/src/wrappers.dart b/lib/src/wrappers.dart |
index fcd33151c28f5f8caae5df08253704059c870a52..c44742709b1d9046a989fcec4aeffb64e745d4d5 100644 |
--- a/lib/src/wrappers.dart |
+++ b/lib/src/wrappers.dart |
@@ -5,6 +5,7 @@ |
import "dart:collection"; |
import "dart:math" as math; |
+import "typed_wrappers.dart"; |
import "unmodifiable_wrappers.dart"; |
typedef K _KeyForValue<K, V>(V value); |
@@ -81,27 +82,53 @@ abstract class _DelegatingIterableBase<E> implements Iterable<E> { |
String toString() => _base.toString(); |
} |
-/// Creates an [Iterable] that delegates all operations to a base iterable. |
+/// An [Iterable] that delegates all operations to a base iterable. |
/// |
-/// This class can be used hide non-`Iterable` methods of an iterable object, |
+/// This class can be used to hide non-`Iterable` methods of an iterable object, |
/// or it can be extended to add extra functionality on top of an existing |
/// iterable object. |
class DelegatingIterable<E> extends _DelegatingIterableBase<E> { |
final Iterable<E> _base; |
- /// Create a wrapper that forwards operations to [base]. |
+ /// Creates a wrapper that forwards operations to [base]. |
const DelegatingIterable(Iterable<E> base) : _base = base; |
+ |
+ /// Creates a wrapper that asserts the types of values in [base]. |
+ /// |
+ /// This soundly converts an [Iterable] without a generic type to an |
+ /// `Iterable<E>` by asserting that its elements are instances of `E` whenever |
+ /// they're accessed. If they're not, it throws a [CastError]. |
+ /// |
+ /// This forwards all operations to [base], so any changes in [base] will be |
+ /// reflected in [this]. If [base] is already an `Iterable<E>`, it's returned |
+ /// unmodified. |
Lasse Reichstein Nielsen
2016/03/29 12:56:25
So, if it's an Iterable<E>, then it's assumed to o
nweiz
2016/03/29 20:18:05
I believe in strong mode it's guaranteed that "is
Lasse Reichstein Nielsen
2016/03/29 20:49:58
Then keep "typed". As long as it's described what
|
+ static Iterable/*<E>*/ typed/*<E>*/(Iterable base) => |
+ base is Iterable/*<E>*/ ? base : new TypedIterable/*<E>*/(base); |
} |
-/// Creates a [List] that delegates all operations to a base list. |
+/// A [List] that delegates all operations to a base list. |
/// |
-/// This class can be used hide non-`List` methods of a list object, |
-/// or it can be extended to add extra functionality on top of an existing |
-/// list object. |
+/// This class can be used to hide non-`List` methods of a list object, or it |
+/// can be extended to add extra functionality on top of an existing list |
+/// object. |
class DelegatingList<E> extends DelegatingIterable<E> implements List<E> { |
const DelegatingList(List<E> base) : super(base); |
+ /// Creates a wrapper that asserts the types of values in [base]. |
+ /// |
+ /// This soundly converts a [List] without a generic type to a `List<E>` by |
+ /// asserting that its elements are instances of `E` whenever they're |
+ /// accessed. If they're not, it throws a [CastError]. Note that even if an |
+ /// operation throws a [CastError], it may still mutate the underlying |
+ /// collection. |
+ /// |
+ /// This forwards all operations to [base], so any changes in [base] will be |
+ /// reflected in [this]. If [base] is already a `List<E>`, it's returned |
+ /// unmodified. |
+ static List/*<E>*/ typed/*<E>*/(List base) => |
+ base is List/*<E>*/ ? base : new TypedList/*<E>*/(base); |
+ |
List<E> get _listBase => _base; |
E operator [](int index) => _listBase[index]; |
@@ -191,14 +218,27 @@ class DelegatingList<E> extends DelegatingIterable<E> implements List<E> { |
} |
-/// Creates a [Set] that delegates all operations to a base set. |
+/// A [Set] that delegates all operations to a base set. |
/// |
-/// This class can be used hide non-`Set` methods of a set object, |
-/// or it can be extended to add extra functionality on top of an existing |
-/// set object. |
+/// This class can be used to hide non-`Set` methods of a set object, or it can |
+/// be extended to add extra functionality on top of an existing set object. |
class DelegatingSet<E> extends DelegatingIterable<E> implements Set<E> { |
const DelegatingSet(Set<E> base) : super(base); |
+ /// Creates a wrapper that asserts the types of values in [base]. |
+ /// |
+ /// This soundly converts a [Set] without a generic type to a `Set<E>` by |
+ /// asserting that its elements are instances of `E` whenever they're |
+ /// accessed. If they're not, it throws a [CastError]. Note that even if an |
+ /// operation throws a [CastError], it may still mutate the underlying |
+ /// collection. |
+ /// |
+ /// This forwards all operations to [base], so any changes in [base] will be |
+ /// reflected in [this]. If [base] is already a `Set<E>`, it's returned |
+ /// unmodified. |
+ static Set/*<E>*/ typed/*<E>*/(Set base) => |
+ base is Set/*<E>*/ ? base : new TypedSet/*<E>*/(base); |
+ |
Set<E> get _setBase => _base; |
bool add(E value) => _setBase.add(value); |
@@ -242,14 +282,28 @@ class DelegatingSet<E> extends DelegatingIterable<E> implements Set<E> { |
Set<E> toSet() => new DelegatingSet<E>(_setBase.toSet()); |
} |
-/// Creates a [Queue] that delegates all operations to a base queue. |
+/// A [Queue] that delegates all operations to a base queue. |
/// |
-/// This class can be used hide non-`Queue` methods of a queue object, |
-/// or it can be extended to add extra functionality on top of an existing |
-/// queue object. |
+/// This class can be used to hide non-`Queue` methods of a queue object, or it |
+/// can be extended to add extra functionality on top of an existing queue |
+/// object. |
class DelegatingQueue<E> extends DelegatingIterable<E> implements Queue<E> { |
const DelegatingQueue(Queue<E> queue) : super(queue); |
+ /// Creates a wrapper that asserts the types of values in [base]. |
+ /// |
+ /// This soundly converts a [Queue] without a generic type to a `Queue<E>` by |
+ /// asserting that its elements are instances of `E` whenever they're |
+ /// accessed. If they're not, it throws a [CastError]. Note that even if an |
+ /// operation throws a [CastError], it may still mutate the underlying |
+ /// collection. |
+ /// |
+ /// This forwards all operations to [base], so any changes in [base] will be |
+ /// reflected in [this]. If [base] is already a `Queue<E>`, it's returned |
+ /// unmodified. |
+ static Queue/*<E>*/ typed/*<E>*/(Queue base) => |
+ base is Queue/*<E>*/ ? base : new TypedQueue/*<E>*/(base); |
+ |
Queue<E> get _baseQueue => _base; |
void add(E value) { |
@@ -283,9 +337,9 @@ class DelegatingQueue<E> extends DelegatingIterable<E> implements Queue<E> { |
E removeLast() => _baseQueue.removeLast(); |
} |
-/// Creates a [Map] that delegates all operations to a base map. |
+/// A [Map] that delegates all operations to a base map. |
/// |
-/// This class can be used hide non-`Map` methods of an object that extends |
+/// This class can be used to hide non-`Map` methods of an object that extends |
/// `Map`, or it can be extended to add extra functionality on top of an |
/// existing map object. |
class DelegatingMap<K, V> implements Map<K, V> { |
@@ -293,6 +347,20 @@ class DelegatingMap<K, V> implements Map<K, V> { |
const DelegatingMap(Map<K, V> base) : _base = base; |
+ /// Creates a wrapper that asserts the types of keys and values in [base]. |
+ /// |
+ /// This soundly converts a [Map] without generic types to a `Map<K, V>` by |
+ /// asserting that its keys are instances of `E` and its values are instances |
+ /// of `V` whenever they're accessed. If they're not, it throws a [CastError]. |
+ /// Note that even if an operation throws a [CastError], it may still mutate |
+ /// the underlying collection. |
+ /// |
+ /// This forwards all operations to [base], so any changes in [base] will be |
+ /// reflected in [this]. If [base] is already a `Map<K, V>`, it's returned |
+ /// unmodified. |
+ static Map/*<K, V>*/ typed/*<K, V>*/(Map base) => |
+ base is Map<K, V> ? base : new TypedMap<K, V>(base); |
+ |
V operator [](Object key) => _base[key]; |
void operator []=(K key, V value) { |