Sprinkle some mixin magic incantations (#10442)

This prevents some of our mixins from being subclassed.

Also, move mixins to using 'extends' instead of 'implements' for
future compatibility with Dart changes.

Also, rename a class that had Mixin in the name but was not a mixin.
This commit is contained in:
Ian Hickson 2017-06-02 15:54:22 -07:00 committed by GitHub
parent 38891a2f72
commit 9eae8b83ff
22 changed files with 128 additions and 26 deletions

View file

@ -115,6 +115,10 @@ class AlwaysStoppedAnimation<T> extends Animation<T> {
/// given [parent] Animation. To implement an [Animation] that proxies to a
/// parent, this class plus implementing "T get value" is all that is necessary.
abstract class AnimationWithParentMixin<T> {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory AnimationWithParentMixin._() => null;
/// The animation whose value this animation will proxy.
///
/// This animation must remain the same for the lifetime of this object. If

View file

@ -9,12 +9,20 @@ import 'package:flutter/foundation.dart';
import 'animation.dart';
abstract class _ListenerMixin {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory _ListenerMixin._() => null;
void didRegisterListener();
void didUnregisterListener();
}
/// A mixin that helps listen to another object only when this object has registered listeners.
abstract class AnimationLazyListenerMixin implements _ListenerMixin {
abstract class AnimationLazyListenerMixin extends _ListenerMixin {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory AnimationLazyListenerMixin._() => null;
int _listenerCounter = 0;
@override
@ -47,7 +55,11 @@ abstract class AnimationLazyListenerMixin implements _ListenerMixin {
/// A mixin that replaces the didRegisterListener/didUnregisterListener contract
/// with a dispose contract.
abstract class AnimationEagerListenerMixin implements _ListenerMixin {
abstract class AnimationEagerListenerMixin extends _ListenerMixin {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory AnimationEagerListenerMixin._() => null;
@override
void didRegisterListener() { }
@ -60,9 +72,13 @@ abstract class AnimationEagerListenerMixin implements _ListenerMixin {
void dispose() { }
}
/// A mixin that implements the addListener/removeListener protocol and notifies
/// all the registered listeners when notifyListeners is called.
/// A mixin that implements the [addListener]/[removeListener] protocol and notifies
/// all the registered listeners when [notifyListeners] is called.
abstract class AnimationLocalListenersMixin extends _ListenerMixin {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory AnimationLocalListenersMixin._() => null;
final ObserverList<VoidCallback> _listeners = new ObserverList<VoidCallback>();
/// Calls the listener every time the value of the animation changes.
@ -111,6 +127,10 @@ abstract class AnimationLocalListenersMixin extends _ListenerMixin {
/// and notifies all the registered listeners when notifyStatusListeners is
/// called.
abstract class AnimationLocalStatusListenersMixin extends _ListenerMixin {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory AnimationLocalStatusListenersMixin._() => null;
final ObserverList<AnimationStatusListener> _statusListeners = new ObserverList<AnimationStatusListener>();
/// Calls listener every time the status of the animation changes.

View file

@ -6,6 +6,10 @@ import 'package:meta/meta.dart';
/// A mixin that helps dump string representations of trees.
abstract class TreeDiagnosticsMixin {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory TreeDiagnosticsMixin._() => null;
@override
String toString() => '$runtimeType#$hashCode';

View file

@ -15,7 +15,10 @@ import 'hit_test.dart';
import 'pointer_router.dart';
/// A binding for the gesture subsystem.
abstract class GestureBinding extends BindingBase implements HitTestable, HitTestDispatcher, HitTestTarget {
abstract class GestureBinding extends BindingBase with HitTestable, HitTestDispatcher, HitTestTarget {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory GestureBinding._() => null;
@override
void initInstances() {

View file

@ -6,6 +6,10 @@ import 'events.dart';
/// An object that can hit-test pointers.
abstract class HitTestable { // ignore: one_member_abstracts
// This class is intended to be used as an interface with the implements
// keyword, and should not be extended directly.
factory HitTestable._() => null;
/// Check whether the given position hits this object.
///
/// If this given position hits this object, consider adding a [HitTestEntry]
@ -15,12 +19,20 @@ abstract class HitTestable { // ignore: one_member_abstracts
/// An object that can dispatch events.
abstract class HitTestDispatcher { // ignore: one_member_abstracts
// This class is intended to be used as an interface with the implements
// keyword, and should not be extended directly.
factory HitTestDispatcher._() => null;
/// Override this method to dispatch events.
void dispatchEvent(PointerEvent event, HitTestResult result);
}
/// An object that can handle events.
abstract class HitTestTarget { // ignore: one_member_abstracts
// This class is intended to be used as an interface with the implements
// keyword, and should not be extended directly.
factory HitTestTarget._() => null;
/// Override this method to receive events.
void handleEvent(PointerEvent event, HitTestEntry entry);
}

View file

@ -20,7 +20,11 @@ import 'view.dart';
export 'package:flutter/gestures.dart' show HitTestResult;
/// The glue between the render tree and the Flutter engine.
abstract class RendererBinding extends BindingBase implements SchedulerBinding, ServicesBinding, HitTestable {
abstract class RendererBinding extends BindingBase with SchedulerBinding, ServicesBinding, HitTestable {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory RendererBinding._() => null;
@override
void initInstances() {
super.initInstances();

View file

@ -8,7 +8,7 @@ import 'box.dart';
import 'object.dart';
/// Parent data for use with [RenderListBody].
class ListBodyParentData extends ContainerBoxParentDataMixin<RenderBox> { }
class ListBodyParentData extends ContainerBoxParentData<RenderBox> { }
typedef double _ChildSizingFunction(RenderBox child);

View file

@ -530,7 +530,10 @@ class BoxParentData extends ParentData {
/// Abstract ParentData subclass for RenderBox subclasses that want the
/// ContainerRenderObjectMixin.
abstract class ContainerBoxParentDataMixin<ChildType extends RenderObject> extends BoxParentData with ContainerParentDataMixin<ChildType> { }
///
/// This is a convenience class that mixes in the relevant classes with
/// the relevant type arguments.
abstract class ContainerBoxParentData<ChildType extends RenderObject> extends BoxParentData with ContainerParentDataMixin<ChildType> { }
enum _IntrinsicDimension { minWidth, maxWidth, minHeight, maxHeight }
@ -714,13 +717,13 @@ class _IntrinsicDimensionsCacheEntry {
/// [parentData]. The class used for [parentData] must itself have the
/// [ContainerParentDataMixin] class mixed into it; this is where
/// [ContainerRenderObjectMixin] stores the linked list. A [ParentData] class
/// can extend [ContainerBoxParentDataMixin]; this is essentially
/// can extend [ContainerBoxParentData]; this is essentially
/// [BoxParentData] mixed with [ContainerParentDataMixin]. For example, if a
/// `RenderFoo` class wanted to have a linked list of [RenderBox] children, one
/// might create a `FooParentData` class as follows:
///
/// ```dart
/// class FooParentData extends ContainerBoxParentDataMixin<RenderBox> {
/// class FooParentData extends ContainerBoxParentData<RenderBox> {
/// // (any fields you might need for these children)
/// }
/// ```
@ -2024,7 +2027,10 @@ abstract class RenderBox extends RenderObject {
/// By convention, this class doesn't override any members of the superclass.
/// Instead, it provides helpful functions that subclasses can call as
/// appropriate.
abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, ParentDataType extends ContainerBoxParentDataMixin<ChildType>> implements ContainerRenderObjectMixin<ChildType, ParentDataType> {
abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, ParentDataType extends ContainerBoxParentData<ChildType>> implements ContainerRenderObjectMixin<ChildType, ParentDataType> {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory RenderBoxContainerDefaultsMixin._() => null;
/// Returns the baseline of the first child with a baseline.
///

View file

@ -10,7 +10,7 @@ import 'object.dart';
// For SingleChildLayoutDelegate and RenderCustomSingleChildLayoutBox, see shifted_box.dart
/// [ParentData] used by [RenderCustomMultiChildLayoutBox].
class MultiChildLayoutParentData extends ContainerBoxParentDataMixin<RenderBox> {
class MultiChildLayoutParentData extends ContainerBoxParentData<RenderBox> {
/// An object representing the identity of this child.
Object id;

View file

@ -29,7 +29,7 @@ enum FlexFit {
}
/// Parent data for use with [RenderFlex].
class FlexParentData extends ContainerBoxParentDataMixin<RenderBox> {
class FlexParentData extends ContainerBoxParentData<RenderBox> {
/// The flex factor to use for this child
///
/// If null or zero, the child is inflexible and determines its own size. If
@ -48,7 +48,7 @@ class FlexParentData extends ContainerBoxParentDataMixin<RenderBox> {
FlexFit fit;
@override
String toString() => '${super.toString()}; flex=$flex';
String toString() => '${super.toString()}; flex=$flex; fit=$fit';
}
/// How much space should be occupied in the main axis.

View file

@ -143,7 +143,7 @@ int _getAlphaFromOpacity(double opacity) => (opacity * 255).round();
/// transformation matrix, which is private to the [RenderFlow]. To set the
/// matrix, use the [FlowPaintingContext.paintChild] function from an override
/// of the [FlowDelegate.paintChildren] function.
class FlowParentData extends ContainerBoxParentDataMixin<RenderBox> {
class FlowParentData extends ContainerBoxParentData<RenderBox> {
Matrix4 _transform;
}

View file

@ -2739,7 +2739,11 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
/// Generic mixin for render objects with one child.
///
/// Provides a child model for a render object subclass that has a unique child.
abstract class RenderObjectWithChildMixin<ChildType extends RenderObject> implements RenderObject {
abstract class RenderObjectWithChildMixin<ChildType extends RenderObject> extends RenderObject {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory RenderObjectWithChildMixin._() => null;
/// Checks whether the given render object has the correct [runtimeType] to be
/// a child of this render object.
///
@ -2816,7 +2820,11 @@ abstract class RenderObjectWithChildMixin<ChildType extends RenderObject> implem
}
/// Parent data to support a doubly-linked list of children.
abstract class ContainerParentDataMixin<ChildType extends RenderObject> implements ParentData {
abstract class ContainerParentDataMixin<ChildType extends RenderObject> extends ParentData {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory ContainerParentDataMixin._() => null;
/// The previous sibling in the parent's child list.
ChildType previousSibling;
/// The next sibling in the parent's child list.
@ -2847,7 +2855,10 @@ abstract class ContainerParentDataMixin<ChildType extends RenderObject> implemen
///
/// Provides a child model for a render object subclass that has a doubly-linked
/// list of children.
abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, ParentDataType extends ContainerParentDataMixin<ChildType>> implements RenderObject {
abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, ParentDataType extends ContainerParentDataMixin<ChildType>> extends RenderObject {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory ContainerRenderObjectMixin._() => null;
bool _debugUltimatePreviousSiblingOf(ChildType child, { ChildType equals }) {
ParentDataType childParentData = child.parentData;

View file

@ -50,7 +50,11 @@ class RenderProxyBox extends RenderBox with RenderObjectWithChildMixin<RenderBox
/// of [RenderProxyBox] is desired but inheriting from [RenderProxyBox] is
/// impractical (e.g. because you want to mix in other classes as well).
// TODO(ianh): Remove this class once https://github.com/dart-lang/sdk/issues/15101 is fixed
abstract class RenderProxyBoxMixin implements RenderBox, RenderObjectWithChildMixin<RenderBox> {
abstract class RenderProxyBoxMixin extends RenderBox with RenderObjectWithChildMixin<RenderBox> {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory RenderProxyBoxMixin._() => null;
@override
void setupParentData(RenderObject child) {
// We don't actually use the offset argument in BoxParentData, so let's

View file

@ -138,7 +138,7 @@ class RelativeRect {
}
/// Parent data for use with [RenderStack].
class StackParentData extends ContainerBoxParentDataMixin<RenderBox> {
class StackParentData extends ContainerBoxParentData<RenderBox> {
/// The distance by which the child's top edge is inset from the top of the stack.
double top;

View file

@ -20,7 +20,11 @@ import 'viewport_offset.dart';
/// content, which can be controlled by a [ViewportOffset]. This interface lets
/// the framework recognize such render objects and interact with them without
/// having specific knowledge of all the various types of viewports.
abstract class RenderAbstractViewport implements RenderObject {
abstract class RenderAbstractViewport extends RenderObject {
// This class is intended to be used as an interface with the implements
// keyword, and should not be extended directly.
factory RenderAbstractViewport._() => null;
/// Returns the [RenderAbstractViewport] that most tightly encloses the given
/// render object.
///

View file

@ -59,7 +59,7 @@ class _RunMetrics {
}
/// Parent data for use with [RenderWrap].
class WrapParentData extends ContainerBoxParentDataMixin<RenderBox> {
class WrapParentData extends ContainerBoxParentData<RenderBox> {
int _runIndex = 0;
}

View file

@ -159,6 +159,9 @@ enum SchedulerPhase {
/// priority and are executed in priority order according to a
/// [schedulingStrategy].
abstract class SchedulerBinding extends BindingBase {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory SchedulerBinding._() => null;
@override
void initInstances() {

View file

@ -17,6 +17,10 @@ import 'platform_messages.dart';
/// the licenses found in the `LICENSE` file stored at the root of the asset
/// bundle.
abstract class ServicesBinding extends BindingBase {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory ServicesBinding._() => null;
@override
void initInstances() {
super.initInstances();

View file

@ -22,6 +22,11 @@ export 'dart:ui' show AppLifecycleState, Locale;
/// Interface for classes that register with the Widgets layer binding.
///
/// See [WidgetsBinding.addObserver] and [WidgetsBinding.removeObserver].
///
/// This class can be extended directly, to get default behaviors for all of the
/// handlers, or can used with the `implements` keyword, in which case all the
/// handlers must be implemented (and the analyzer will list those that have
/// been omitted).
abstract class WidgetsBindingObserver {
/// Called when the system tells the app to pop the current route.
/// For example, on Android, this is called when the user presses
@ -63,7 +68,11 @@ abstract class WidgetsBindingObserver {
}
/// The glue between the widgets layer and the Flutter engine.
abstract class WidgetsBinding extends BindingBase implements GestureBinding, RendererBinding {
abstract class WidgetsBinding extends BindingBase with GestureBinding, RendererBinding {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory WidgetsBinding._() => null;
@override
void initInstances() {
super.initInstances();

View file

@ -15,6 +15,10 @@ import 'scroll_metrics.dart';
///
/// This is used by [ScrollNotification] and [OverscrollIndicatorNotification].
abstract class ViewportNotificationMixin extends Notification {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory ViewportNotificationMixin._() => null;
/// The number of viewports that this notification has bubbled through.
///
/// Typically listeners only respond to notifications with a [depth] of zero.

View file

@ -166,7 +166,11 @@ abstract class _SliverPersistentHeaderRenderObjectWidget extends RenderObjectWid
}
}
abstract class _RenderSliverPersistentHeaderForWidgetsMixin implements RenderSliverPersistentHeader {
abstract class _RenderSliverPersistentHeaderForWidgetsMixin extends RenderSliverPersistentHeader {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory _RenderSliverPersistentHeaderForWidgetsMixin._() => null;
_SliverPersistentHeaderElement _element;
@override

View file

@ -73,7 +73,10 @@ class TickerMode extends InheritedWidget {
/// This mixin only supports vending a single ticker. If you might have multiple
/// [AnimationController] objects over the lifetime of the [State], use a full
/// [TickerProviderStateMixin] instead.
abstract class SingleTickerProviderStateMixin implements State<dynamic>, TickerProvider { // ignore: TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, https://github.com/dart-lang/sdk/issues/25232
abstract class SingleTickerProviderStateMixin extends State<dynamic> implements TickerProvider { // ignore: TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, https://github.com/dart-lang/sdk/issues/25232
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory SingleTickerProviderStateMixin._() => null;
Ticker _ticker;
@ -150,7 +153,10 @@ abstract class SingleTickerProviderStateMixin implements State<dynamic>, TickerP
/// If you only have a single [Ticker] (for example only a single
/// [AnimationController]) for the lifetime of your [State], then using a
/// [SingleTickerProviderStateMixin] is more efficient. This is the common case.
abstract class TickerProviderStateMixin implements State<dynamic>, TickerProvider { // ignore: TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, https://github.com/dart-lang/sdk/issues/25232
abstract class TickerProviderStateMixin extends State<dynamic> implements TickerProvider { // ignore: TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, https://github.com/dart-lang/sdk/issues/25232
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory TickerProviderStateMixin._() => null;
Set<Ticker> _tickers;