Преглед на файлове

Support `external impl` in class and adapter scopes. (#905)

josh11b преди 4 години
родител
ревизия
b08e3fedeb
променени са 1 файла, в които са добавени 61 реда и са изтрити 4 реда
  1. 61 4
      docs/design/generics/details.md

+ 61 - 4
docs/design/generics/details.md

@@ -449,7 +449,49 @@ external impl Point3 as Vector {
 
 With this definition, `Point3` includes `Add` in its API but not `Scale`, while
 `Point3 as Vector` includes both. This maintains the property that you can
-determine the API of a type by looking at its definition.
+determine the API of a type by looking at its definition. In this case, the
+`external impl` may be defined lexically inside the scope of the class.
+
+```
+class Point3 {
+  var x: Double;
+  var y: Double;
+  fn Add[me: Self](b: Self) -> Self {
+    return {.x = a.x + b.x, .y = a.y + b.y};
+  }
+  // Type before `as` is optional and defaults to the current class.
+  external impl as Vector {
+    alias Add = Point3.Add;  // Syntax TBD
+    fn Scale[me: Self](v: Double) -> Self {
+      return {.x = a.x * v, .y = a.y * v};
+    }
+  }
+}
+
+// OR:
+
+class Point3 {
+  var x: Double;
+  var y: Double;
+  external impl as Vector {
+    fn Add[me: Self](b: Self) -> Self {
+      return {.x = a.x + b.x, .y = a.y + b.y};
+    }
+    fn Scale[me: Self](v: Double) -> Self {
+      return {.x = a.x * v, .y = a.y * v};
+    }
+  }
+  alias Add = Vector.Add;  // Syntax TBD
+}
+```
+
+Being defined lexically inside the class means that implementation is available
+to other members defined in the class. For example, it would allow implementing
+another interface or method that requires this interface to be implemented.
+
+**Open question:** Do implementations need to be defined lexically inside the
+class to get access to private members, or is it sufficient to be defined in the
+same library as the class?
 
 **Rejected alternative:** We could allow types to have different APIs in
 different files based on explicit configuration in that file. For example, we
@@ -1632,9 +1674,24 @@ Unlike the similar `class B extends A` notation, `adaptor B extends A` is
 permitted even if `A` is a final class. Also, there is no implicit conversion
 from `B` to `A`, matching `adapter`...`for` but unlike class extension.
 
-**Future work:** We may need additional mechanisms for changing the API in the
-adapter. For example, to resolve conflicts we might want to be able to move the
-implementation of a specific interface into an [external impl](#external-impl).
+To avoid or resolve name conflicts between interfaces, an `impl` may be declared
+[`external`](#external-impl). The names in that interface may then be pulled in
+individually or renamed using `alias` declarations.
+
+```
+adapter SongRenderToPrintDriver extends Song {
+  // Add a new `Print()` member function.
+  fn Print[me: Self]() { ... }
+
+  // Avoid name conflict with new `Print` function by making
+  // the implementation of the `Printable` interface external.
+  external impl as Printable = Song as Printable;
+
+  // Make the `Print` function from `Printable` available
+  // under the name `PrintToScreen`.
+  alias PrintToScreen = Printable.Print;
+}
+```
 
 ### Use case: Using independent libraries together