Add casting for ObservableList. (#66)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9636dfb..52ffcc1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+## 0.23.0
+
+* Added `ObservableList.castFrom`, similar to `List.castFrom`.
+
+* Changed `ObservableList`'s `cast` and `retype` function to create a forwarding
+ instance of `ObservableList` instead of an instance of `List`.
+
## 0.22.0
* Added `ObservableMap.castFrom`, similar to `Map.castFrom`.
diff --git a/lib/src/observable_list.dart b/lib/src/observable_list.dart
index b5ae6d3..b983e54 100644
--- a/lib/src/observable_list.dart
+++ b/lib/src/observable_list.dart
@@ -15,6 +15,20 @@
/// removed, or replaced, then observers that are listening to [changes]
/// will be notified.
class ObservableList<E> extends ListBase<E> with Observable {
+ /// Adapts [source] to be a `ObservableList<T>`.
+ ///
+ /// Any time the list would produce an element that is not a [T],
+ /// the element access will throw.
+ ///
+ /// Any time a [T] value is attempted stored into the adapted list,
+ /// the store will throw unless the value is also an instance of [S].
+ ///
+ /// If all accessed elements of [source] are actually instances of [T],
+ /// and if all elements stored into the returned list are actually instance
+ /// of [S], then the returned list can be used as a `ObservableList<T>`.
+ static ObservableList<T> castFrom<S, T>(ObservableList<S> source) =>
+ new ObservableList<T>._spy(source._list.cast<T>());
+
List<ListChangeRecord<E>> _listRecords;
StreamController<List<ListChangeRecord<E>>> _listChanges;
@@ -44,6 +58,41 @@
/// the list will be the order provided by the iterator of [other].
ObservableList.from(Iterable other) : _list = new List<E>.from(other);
+ ObservableList._spy(List<E> other) : _list = other;
+
+ /// Returns a view of this list as a list of [T] instances, if necessary.
+ ///
+ /// If this list is already a `ObservableList<T>`, it is returned unchanged.
+ ///
+ /// If this list contains only instances of [T], all read operations
+ /// will work correctly. If any operation tries to access an element
+ /// that is not an instance of [T], the access will throw instead.
+ ///
+ /// Elements added to the list (e.g., by using [add] or [addAll])
+ /// must be instance of [T] to be valid arguments to the adding function,
+ /// and they must be instances of [E] as well to be accepted by
+ /// this list as well.
+ @override
+ ObservableList<T> cast<T>() {
+ if (this is ObservableList<T>) {
+ return this as ObservableList<T>;
+ }
+ return retype<T>();
+ }
+
+ /// Returns a view of this list as a list of [T] instances.
+ ///
+ /// If this list contains only instances of [T], all read operations
+ /// will work correctly. If any operation tries to access an element
+ /// that is not an instance of [T], the access will throw instead.
+ ///
+ /// Elements added to the list (e.g., by using [add] or [addAll])
+ /// must be instance of [T] to be valid arguments to the adding function,
+ /// and they must be instances of [E] as well to be accepted by
+ /// this list as well.
+ @override
+ ObservableList<T> retype<T>() => ObservableList.castFrom<E, T>(this);
+
/// The stream of summarized list changes, delivered asynchronously.
///
/// Each list change record contains information about an individual mutation.
diff --git a/pubspec.yaml b/pubspec.yaml
index 0a67bfc..6a8f38b 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: observable
-version: 0.22.0
+version: 0.23.0
author: Dart Team <misc@dartlang.org>
description: Support for marking objects as observable
homepage: https://github.com/dart-lang/observable