Skip to content

"includes" instead of "implements" for view composition #2547

@munificent

Description

@munificent

The views proposal uses implements to allow one view type V1 to build off other view types V2, etc. As I understand it, this clause does two things:

  1. All of the instance members defined by V2 are made accessible as instance members on V1. By "instance" here, I mean that the constructors and static members of V2 are not made available. The dispatch is still purely static. It's almost as if the instance declarations in V2 have been textually copied to V1.

  2. V1 becomes a subtype of V2. This allows establishing a subtype hierarchy among a family of related view types who all share a related representation type.

This behavior seems totally fine to me. However, I find implements a confusing word to express that, for a couple of reasons:

  • In classes, implements specifically means that you do not inherit any implementation. Of course, with views, there is no real "inheritance" going on, it's just that the subtyping induced allows the members on V2 to be available as extension members on V1. But informally, it feels very strange that an implements clause gives you implemented functionality.

  • In classes, implements adds a requirement to the class. When you add an implements, your class now has an obligation to define or inherit implementations of all of those members. Adding implements can require you to do work in your class declaration. With views, implements gives you stuff "for free" and doesn't require you to add anything (except possibly redeclaring to avoid collisions).

  • In classes, and in other languages, implements implies some level of runtime polymorphism and dynamic or virtual dispatch. It suggests that the thing being implemented is an interface and the class can now be used wherever that interface is allowed, and its instance members are now polymorphic implementations of that protocol. None of that applies to views where all dispatch is entirely static.

In short, it feels like a confusing keyword choice to me. Instead, I propose includes:

view class V1(int i) {
  void v1() {}
}

view class V2(int i) {
  void v2() {}
}

view class V3 includes V1, V2 {}

I think that word conveys that all of the functionality defined by the superviews is now available by the subview.

It might be confusing that a new word includes also induces a subtype relation. But I believe we already have that in Dart and it doesn't seem to cause much confusion in practice. The keywords extends, implements, and with all also mean that the class containing that clause becomes a subtype of the type in the clause. So this would just be one more keyword where that's true.

I also think the subtyping aspect is less important than the code reuse aspect. When users are reading a program, they mostly want to know where the code that gets called is and how it is reached. Using includes suggests that "Ah, this method I can see being called on V3 must have been included from V1".

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions