Using mixins for private fields or abstract methods Dart - dart

I am experimenting with Dart mixins and noticed that
You can use private fields in mixins
Even abstract methods like abstract classes.
Imagine you have few abstract methods no need to create an abstract ad extend it, you can collect them inside a mixin and re-use it.
The discussion goes whether you like to have inheritance within your design
Here is a code snippet:
import 'package:flutter/cupertino.dart';
mixin Favourite {
bool _isFavourite = false;
bool get isFavourite;
}
class ProductProvider
with Favourite, ChangeNotifier
implements Comparable<ProductProvider> {
final String id;
final String title;
final String description;
final String imageUrl;
final double price;
ProductProvider({
required this.id,
required this.title,
required this.description,
required this.imageUrl,
required this.price,
});
ProductProvider.noPrice({
required this.id,
required this.title,
required this.description,
required this.imageUrl,
bool isFavourite = false,
}) : price = 0.0;
toggleFavourite() {
this._isFavourite = !this._isFavourite;
notifyListeners();
}
#override
bool get isFavourite => _isFavourite;
factory ProductProvider.fromJSON(Map<String, dynamic> json) {
return json['price'] != null
? ProductProvider(
id: json['id'],
title: json['title'],
description: json['description'],
imageUrl: json['imageUrl'],
price:
json['price'] is int ? json['price'].toDouble() : json['price'])
: ProductProvider.noPrice(
id: json['id'],
title: json['title'],
description: json['description'],
imageUrl: json['imageUrl'],
isFavourite: json['isFavourite'] ?? false,
);
}
#override
int compareTo(ProductProvider other) {
return (price - other.price).toInt();
}
}

Related

How to pass null in a method?

class Foo {
final int? i;
Foo({this.i});
Foo copyWith({int? x}) {
return Foo(i: x ?? i);
}
}
void main() {
final foo = Foo(i: 0);
foo.copyWith(x: null);
print(foo.i); // prints `0` but should print `null`.
}
How can I actually pass null value to the method? In earlier Dart version copyWith() and copyWith(x: null) were two different things.
Note: I'm not looking for workarounds like making a new variable, like isNull and then deciding whether to pass null or not based on its value.
With simple copyWithwhit Dart null-safety you can't override value by null because if id is null return this.id. You need to override the value by null but not return with another value. It can solve in a few ways but I will give you the best example.
void main() {
final user = User(name: 'Dave', id: 110);
User copy = user.copyWith(id: null);
print(copy.toString()); // prints User(name: Dave, id: null).
}
class User {
User({required this.name, this.id});
final String name;
final int? id;
UserCopyWith get copyWith => _UserCopyWith(this);
#override
String toString() => 'User(name: $name, id: $id)';
}
abstract class UserCopyWith {
User call({
String name,
int? id,
});
}
class _UserCopyWith implements UserCopyWith {
_UserCopyWith(this.value);
final User value;
static const _undefined = Object();
#override
User call({
Object name = _undefined,
Object? id = _undefined,
}) {
return User(
name: name == _undefined ? value.name : name as String,
id: id == _undefined ? value.id : id as int?,
);
}
}

How do I create an abstract factory?

Is it possible to somehow create an abstract factory method? Maybe what I'm trying to do is possible to implement differently?
abstract class ApiModel {
// Error: A function body must be provided.
factory ApiModel.fromJson(Map<String, dynamic> json);
}
class User extends ApiModel {
final int id;
final String name;
User({required this.id, required this.name});
#override
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'] as int,
name: json['name'] as String,
);
}
}
class ApiResponse<Model extends ApiModel> {
final List<Model> results;
ApiResponse({required this.results});
factory ApiResponse.fromJson(Map<String, dynamic> json) {
return ApiResponse(results: (json['results'] as List).map((item) => Model.fromJson(item)).toList());
}
}
I solved it like this:
factory ApiResponse.fromJson(Map<String, dynamic> json, Model Function(dynamic) mapper) {
return ApiResponse(
info: Info.fromJson(json['info']),
results: (json['results'] as List).map(mapper).toList(),
);
}

i tried to run the code in dart pad, online platform

dart:
As you can see in this .dart code I am trying to print the list of id, there is a Dummy Data class which have a list of details of some product. There is a main function which call a instance (productIdList) of a class name Present.
class DummyData{
List<Product> dummyProduct = [
Product(
id: 'p1',
title: 'Red Shirt',
description: 'A red shirt - it is pretty red!',
price: 29.99,
imageUrl:
'https://cdn.pixabay.com/photo/2016/10/02/22/17/red-t-shirt-1710578_1280.jpg',
),
Product(
id: 'p2',
title: 'Trousers',
description: 'A nice pair of trousers.',
price: 59.99,
imageUrl:
'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e8/Trousers%2C_dress_%28AM_1960.022-8%29.jpg/512px-Trousers%2C_dress_%28AM_1960.022-8%29.jpg',
),
Product(
id: 'p3',
title: 'Yellow Scarf',
description: 'Warm and cozy - exactly what you need for the winter.',
price: 19.99,
imageUrl: 'https://live.staticflickr.com/4043/4438260868_cc79b3369d_z.jpg',
),
Product(
id: 'p4',
title: 'A Pan',
description: 'Prepare any meal you want.',
price: 49.99,
imageUrl:
'https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Cast-Iron-Pan.jpg/1024px-Cast-Iron-Pan.jpg',
),
];
}
class Product{
final String id;
final String title;
final String description;
final double price;
final String imageUrl;
Product({this.id, this.description, this.imageUrl, this.price, this.title});
}
class Present extends DummyData{
void productIdList (){
print(dummyProduct.map((product) =>product.id).toList());
}
}
void main(){
Present obj = Present();
obj.productIdList;
}
The code above will not compile in the latest version of dart due to changes made to support null safety. Specifically the product class. You can fix in a few different ways.
The first approach would be to mark all of the constructor arguments in the Product class as required. This approach makes it so you have to pass in values for every constructor argument.
class Product {
final String id;
final String title;
final String description;
final double price;
final String imageUrl;
Product(
{required this.id,
required this.description,
required this.imageUrl,
required this.price,
required this.title});
}
The other approach would be to make the fields within the product class nullable. In this approach, you are not required to pass in a value for every constructor argument, but when you do not pass in a value the field will be assigned a null value.
class Product {
final String? id;
final String? title;
final String? description;
final double? price;
final String? imageUrl;
Product(
{this.id,
this.description,
this.imageUrl,
this.price,
this.title});
}

extends not work : doesn't have zero argument constructor

class Persons {
final String name;
final String age;
Persons(
this.name,
this.age,
);
void printName() {
print(name);
}
}
class Players extends Persons {}
enter image description here
Edit the class Players
class Players extends Persons {
Players(name, age): super(name, age);
}

how should I use assert in Dart?

I saw exmaple code something like:
class ModelBinding extends StatefulWidget {
ModelBinding({
Key key,
this.initialModel = const GalleryOptions(),
this.child,
}) : assert(initialModel != null),
super(key: key);
...
so I wrote something:
class Person {
String firstName;
Person({name}){
print(name);
}
}
class Employee extends Person {
Employee(String name) : assert(false), super(name: name);
}
main() {
var emp = new Employee('Jason');
}
No matter if it is assert(false) or assert(true), the result is same.
So what is the meaning of assert?
assert is used for debugging and it simply means the condition should be true to proceed. Let me explain:
class MyClass {
final int age;
MyClass({this.age});
void someMethod() {
// using `age` here
}
}
You might face issues in someMethod if age passed is null, so to make sure it isn't null, you use assert like:
class MyClass {
final int age;
MyClass({this.age}) : assert(age != null, "Make sure age isn't null");
void someMethod() {
// using `age` here
}
}

Resources