Giter Site home page Giter Site logo

Comments (9)

MarcelGarus avatar MarcelGarus commented on July 24, 2024 1

Done. The newest version 2.0.0, already published on pub, generates a copy method allowing usage like this:

var freshApple = const Fruit(type: 'apple', color: 'green');
var someApple = freshApple.copy((fruit) => fruit..color = null);
var kiwi = someApple.copy((fruit) => fruit
  ..type = 'Kiwi'
  ..color = 'brown');

The definition looks like this:

/// Copies this [Fruit] with some changed attributes.
Fruit copy(void Function(MutableFruit mutable) changeAttributes) {
  assert(
      changeAttributes != null,
      "You called Fruit.copy, but didn't provide a function for changing "
      "the attributes.\n"
      "If you just want an unchanged copy: You don't need one, just use "
      "the original.");
  var mutable = this.toMutable();
  changeAttributes(mutable);
  return Fruit.fromMutable(mutable);
}

from data_classes.

MarcelGarus avatar MarcelGarus commented on July 24, 2024

That is indeed true, because if a parameter to the method is null, the method doesn't know if it has been explicitly or implicitly set to null. I thought about this before but found no easy way to fix that.
Here are more complicated ways I considered:

Use mutable for copying
On the client code side you can of course convert it to a mutable, the set the fields, then re-convert it to the immutable. Doesn't change the fact that the copyWith method behaves unintuitive in some cases.

Use wrapper function
Change the signature to expect a function for nullable values (just like Iterable's firstWhere(..., orElse: () => otherValueWhichMayBeNull)).
However that leads to code that's a little bit uglier:

mySister = me.copyWith(
  firstName: 'Yvonne',
  photoUrl: () => null,
)

Default values
Third solution, add default values just like dart:ui's hashValues() function, which is defined as

const _default = Object();
int hashValues(Object arg1, [Object arg2 = _default, ...])

In the code you can check if _default == _arg2, so you can see if the user explicitly passed in null. Something like this would probably be the most elegant solution, but we'd need "sample objects" of all the Field's types as default parameter values and that's at least as far as I know impossible to achieve.

If anyone has any other suggestions on how to do this elegantly, you're welcome to share your thoughts.

from data_classes.

ildarsharafutdinov avatar ildarsharafutdinov commented on July 24, 2024

I guess there is also "use mutable in copyWith" option which is similar to builders in BuiltValue:

mySister = me.copyWith((mutableCopy) {
  mutableCopy.firstName = 'Yvonne';
  mutableCopy.photoUrl = null;
});

from data_classes.

MarcelGarus avatar MarcelGarus commented on July 24, 2024

Oh true, that would basically be the first option with some syntactic sugar on top.
If you want to implement that and file a PR, that would be great.

from data_classes.

MarcelGarus avatar MarcelGarus commented on July 24, 2024

Thought about this a bit more.
If you have a simple widget with only non-nullable fields, using a copyWith method with a builder would be unnecessary complex.
That's why I'd rather opt for a copyWith method, where you can change all the non-nullable fields as well as copyWithBuilder method that takes a builder.
Any opinions on that?

from data_classes.

ildarsharafutdinov avatar ildarsharafutdinov commented on July 24, 2024

What params will copyWith contain in case there are nullable fields in the class?
If it continues to accept nullables it will be error prone. If code-gen strips out nullables, it'll be weird.

So I'm in favor of keeping things simple with a single interface for mutations.

from data_classes.

MarcelGarus avatar MarcelGarus commented on July 24, 2024

You're right.

What about we always have a builder method for mutations but if your class has only non-nullable fields, you can optionally explicitly ask for the copyWith method in the annotation, something like @DataClass(generateCopyWith=true).

And if the class contains nullable fields, that will be an error during code generation.

from data_classes.

ildarsharafutdinov avatar ildarsharafutdinov commented on July 24, 2024

I'm still in favor of copyWith((mutable) => ...) :)

E.g. requirements change and a field becomes nullable. A developer will need to remove generateCopyWith=true and then modify all fancy calls of copyWith.
Whereas copyWith((mutable) => ...) won't require changes in existing code.

from data_classes.

MarcelGarus avatar MarcelGarus commented on July 24, 2024

Hmm that is indeed true...
Okay, I'll implement it that way.

from data_classes.

Related Issues (9)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.