google / built_value.dart

Immutable value types, enum classes, and serialization.
https://pub.dev/packages/built_value
BSD 3-Clause "New" or "Revised" License
870 stars 184 forks source link

Can we use "implements" with the Builder? #919

Closed feinstein closed 3 years ago

feinstein commented 4 years ago

I have some VOs that are supposed to take an id value, so I wanted to make it like:

abstract class Identifiable {
  String get id;
  set id(String id);
}

abstract class MyClass implements Built<MyClass, MyClassBuilder>, Identifiable {
  @nullable
  String get id;

This way I could check if is a Type Identifiable before doing something with it.

But this doesn't help as MyClass only has the getter and the setter is supposed to go into the Builder.

I know this more a question than an issue, but I want to check if others have the same issue, maybe that's a common thing I guess, or maybe I am pushing library too much beyond its intent.

dave26199 commented 4 years ago

Yes, it's possible :) see

https://github.com/google/built_value.dart/blob/master/end_to_end_test/lib/polymorphism.dart

Sorry for brief answer, posting from phone :)

feinstein commented 4 years ago

That's very interesting!

Could you make a quick start on how to use polimorphism? That file seems rather complicated. What has to be defined, what can be omitted, how it works, etc?

Sorry for the delay, got caught up on the Jewish high holy days.

feinstein commented 4 years ago

Ok, I made it work apparently, but through some trial and error figuring out what was necessary and what wasn't.

If this could be documented it would be very helpful :).

feinstein commented 4 years ago

UPDATE: You can skip this comment, I figured the issue and don't want to waste your time :)


@dave26199 I am scratching my head for hours and can't figure out the issue.

These are my class and interface declarations:

abstract class Trip implements Built<Trip, TripBuilder>, Identifiable {
  static Serializer<Trip> get serializer => _$tripSerializer;

  @nullable
  String get id;
  String get title;
  // other getters omitted here for simplicity.

  Trip._();

  factory Trip([void Function(TripBuilder) updates]) = _$Trip;
}
import 'package:built_value/built_value.dart';

part 'identifiable.g.dart';

@BuiltValue(instantiable: false)
abstract class Identifiable {
  @nullable
  String get id;

  Identifiable rebuild(void Function(IdentifiableBuilder) updates);
  IdentifiableBuilder toBuilder();
}

Everything complies fine, but at runtime this assertion fails:

assert(Trip is Identifiable);

Is it because Trip doesn't have rebuild and toBuilder?

If so then there's no way I can use assert(Trip is Identifiable);, as I will never match the signatures, right?

Do you know any way around this?

Update: I removed rebuild and toBuilder from Identifiable and I still get an exception at the assert.

feinstein commented 4 years ago

Ok, after a good time of trial and error I figured I can't compare types as assert(Trip is Identifiable);, only variables assert(t is Identifiable). Would love to know is there's any way around this though.

davidmorgan commented 4 years ago

Thanks! I'll leave this open as a request to improve/add docs :)