language
language copied to clipboard
Records, how to assign them to Objects of the same shape
When reading @munificent 's great summary on records I started to wonder what about assignment by value between records and Objects with the same shape, so that you could easily initialize Objects from an existing record.
Maybe even the other way round, so that inside a function that returns a record type you could use a real class Object but could return it if it has the same shape.
That would very much depend on what the "shape" of a class instance is.
Tuples/records are defined by their structure: How many positional elements, which named elements (and their types). Objects are not. Objects do have fields (instance variables), but a private field is an implementation detail, and exposing it in any way not intended by the class author is a breach of abstraction. That's definitely not something we want to do (you want to look at implementation details, you have to use reflection).
The "shape" of a class instance is its public API. If you want to expose some parts of the object state, you provide getters or methods which return it. Sometimes the internal state matches the external API (and then you can have public fields), but the next release of the same code can change that to a public getter/private field without anybody noticing.
So, if a class instance want to be assignable to or from record types, we need some explicit opt-in from the class.
At that point, they can also just add ... toTuple()
and static fromTuple(...)
methods, no extra functionality or implicit coercions needed.
What is the purpose of allowing a class instance to implement a tuple type? If you can use it interchangeably with tuples values, then all tuples will need to be boxed, which removes a lot of the benefit of having tuples anyway. You can already do what you're describing here with classes and interfaces.
I guess this goes back to the fundamental question: Why do we want to add tuples at all?
a to/fromRecord creates again boilerplate code. If a Object has matching public fields an assignment would be possible. toRecord should be possible without a problem
instead of fromRecord I could also imagine that if you have a constructor with the shape of a record that you can pass a record directly to a constructor. Or following this thought allowing to assign a record to functions with a matching signature.
One approach would be to allow records to be spread into function and constructor calls.
(I think this has been discussed here somewhere in another issue.)
For example:
class Foo {
Foo(this.a, {this.b, this.c});
final int a;
final int? b;
final int? c;
}
var r = (1, b: 2, c: 3);
var f = Foo(...r);