class MyMain{
String name;
int mobile;
String gender;
String city;
MyMain({this.name , this.mobile , this.gender , this.city});
}
class MySmall extends MyMain{
int age;
String std;
MySmall({this.age , this.std , name , mobile , gender , city})
: super();
}
main(){
MyMain object1 = MyMain(name:"object1" , mobile: 1234567890 , gender: "M" , city: "xyz");
print(object1.name);
MySmall object2 = MySmall( name: "object2" ,age: 20 , std: "First" , mobile: 0987654321, gender: "M" , city: "XYZ");
print(object2.name);
}
I am trying to create child class and when I retrieve the name of child class it shows null , why so ? Any Solution ?
Your problem is that MySmall does not call the constructor of the class it extends from (MyMain) with the parameters it needs.
The reasons this happens here is because your named arguments is optional and defaults to null if not specified. So when you do super() you are just setting all parameters in the MyMain constructor to null.
I can guess you are running without Dart null-safety (introduced with Dart 2.12) since it would have been complained about the possible assignment of null values on non-nullable types.
You can fix your code by changing your MySmall constructor to:
MySmall(
{this.age, this.std, String name, int mobile, String gender, String city})
: super(name: name, mobile: mobile, gender: gender, city: city);
If we convert your code to be null-safe (and therefore compatible with Dart 2.12.0 and later) it would look like this. The required keyword was introduce to make it possible to have named arguments which is required to be set:
class MyMain {
String name;
int mobile;
String gender;
String city;
MyMain({
required this.name,
required this.mobile,
required this.gender,
required this.city,
});
}
class MySmall extends MyMain {
int age;
String std;
MySmall({
required this.age,
required this.std,
required String name,
required int mobile,
required String gender,
required String city,
}) : super(name: name, mobile: mobile, gender: gender, city: city);
}
void main() {
MyMain object1 = MyMain(
name: "object1",
mobile: 1234567890,
gender: "M",
city: "xyz",
);
print(object1.name); // object1
MySmall object2 = MySmall(
name: "object2",
age: 20,
std: "First",
mobile: 0987654321,
gender: "M",
city: "XYZ",
);
print(object2.name); // object2
}
Related
I am working with some Dart code for a Flutter/Dart class I'm taking. I expected the following code to compile, but it did not:
class Person {
String? name;
int? age;
Person(this.name, this.age);
#override
String toString() {
return "name: $name\nage: $age";
}
}
void main() {
final person = Person(name: 'Joe', age: 30);
print(person);
}
When I made the constructor parameters optional, as below, it does compile:
class Person {
String? name;
int? age;
Person({this.name, this.age});
#override
String toString() {
return "name: $name\nage: $age";
}
}
void main() {
final person = Person(name: 'Joe', age: 30);
print(person);
}
I tried searching the Flutter dev docs for a reason why this is so, or a way to have required parameters with their names in a constructor, but I didn't find anything. I can certainly imagine cases where I would want required constructor parameters to have names.
My pubspec.yaml specifies the following:
environment: sdk: ">=2.12.0 <3.0.0"
Your first example uses what are called "positional parameters" in dart. You cannot call a positional parameter with a name label, which is why the first example does not compile.
The second example uses "named parameters". Any parameter defined within {} is considered a named parameter and must be called using a name label. As explained in the dart language tour, named parameters are optional unless they’re explicitly marked as required.
So simply add the required keyword before any named parameter you want to require.
class Person {
String? name;
int? age;
Person({required this.name, required this.age});
#override
String toString() {
return "name: $name\nage: $age";
}
}
void main() {
final person = Person(name: 'Joe', age: 30);
print(person);
}
class Destination {
String imageUrl;
String city;
String country;
String description;
List<Activity> activities;
Destination({
this.imageUrl,
this.city,
this.country,
this.description,
this.activities,
});
List<Activity> activities = [
Activity(
imageUrl: 'assets/images/stmarksbasilica.jpg',
name: 'St. Mark\'s Basilica',
type: 'Sightseeing Tour',
startTimes: ['9:00 am', '11:00 am'],
rating: 5,
price: 30,
),
Your problem is that named parameters is optional by default in Dart. And if a parameter does not specify a default value, the default value is going to be null.
This is a problem when using null-safety since your variables are declared to never be allowed to have the value null. But by not requiring values for the parameters, there are a risk that some or all of these variables are going to have null as value.
The fix is to use the keyword required to specify that you want a named parameter to be required to get a value when calling the constructor/method. So change your code to:
class Destination {
String imageUrl;
String city;
String country;
String description;
List<Activity> activities;
Destination({
required this.imageUrl,
required this.city,
required this.country,
required this.description,
required this.activities,
});
}
Change this:
Destination({
this.imageUrl ?? "",
this.city ?? "",
this.country ?? "",
this.description ?? "",
this.activities ?? "",
});
now it will work
I have a dart object that includes a field of type Money, which itself is composed of amount and currency:
#JsonSerializable()
class Account {
final String id;
final String type;
final String subtype;
final String origin;
final String name;
final String status;
final String currency;
final Money balance; <== value object
...
}
Money looks something like this:
class Money {
final int amount;
final String currency;
const Money(this.amount, this.currency);
...
}
The above is to be mapped for use by sqflite, therefore the target JSON must be a flat JSON, like:
{
"id": String,
"type": String,
"subtype": String,
"origin": String,
"name": String,
"status": String,
"currency": String,
"balanceAmount": int; <== value object
"balanceCurrency": String; <== value object
}
I understand I can use JsonKey.readValue to extract a composite object from the entire JSON object prior to decoding.
But how can I do the opposite? Grab the two values from the Money instance and map them to balanceAmount and balanceCurrency?
Nothing in the search I did on json_serializable api docs, GitHub issues, or StackOverflow appears to respond to this in particular: how to map one field to two (or more) target keys?
this solution would be better if the generated code used full json in "balance"
like this:
Money.fromJson(json)
But I don't know how to do that :(
import 'package:project/test/money.dart';
import 'package:json_annotation/json_annotation.dart';
part 'account.g.dart';
#JsonSerializable()
class Account {
final String id;
final String type;
final String subtype;
final String origin;
final String name;
final String status;
final String currency;
#JsonKey(fromJson: _dataFromJson)
final Money balance; // <== value object
Account({
required this.id,
required this.type,
required this.subtype,
required this.origin,
required this.name,
required this.status,
required this.currency,
required this.balance,
});
static Money _dataFromJson(Object json) {
if (json is Map<String, dynamic>) {
return Money(amount: json["balanceAmount"], currency: json["balanceCurrency"]);
}
throw ArgumentError.value(
json,
'json',
'Cannot convert the provided data.',
);
// return Money(amount: 0, currency:"");
}
factory Account.fromJson(Map<String, dynamic> json) => Account(
id: json['id'] as String,
type: json['type'] as String,
subtype: json['subtype'] as String,
origin: json['origin'] as String,
name: json['name'] as String,
status: json['status'] as String,
currency: json['currency'] as String,
balance: Money.fromJson(json),
);
Map<String, dynamic> toJson() => _$AccountToJson(this);
}
// {
// "id": String,
// "type": String,
// "subtype": String,
// "origin": String,
// "name": String,
// "status": String,
// "currency": String,
// "balanceAmount": int; <== value object
// "balanceCurrency": String; <== value object
// }
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});
}
I'm new to flutter and graphQL and currently I'm integrating mutations into my app. So, I have the server side using some custom types defined in the schema, but I don't know how to specify them on the flutter side. Let's see some code:
input DiaryGroupPermission {
groupId: Int!
permission: Int!
}
input DiaryInsideCommunity {
communityId: Int!
permissions: [DiaryGroupPermission]!
}
createDiary(community: DiaryInsideCommunity, description: String, title: String!): Diary
But on the client I don't know how to specify the DiaryInsideCommunity inside the mutation.
I've tried something like this:
String createDiary = """
mutation CreateDiary(\$title: String!, \$description: String!, \$community: DiaryInsideCommunity) {
createDiary(
title: \$title,
description: \$description,
community: \$community
) {
id
}
)}""".replaceAll('\n', ' ');
And passing my runMutation as follows:
runMutation({
"title": _generalPage.title(),
"description": _generalPage.description(),
"community": {
"communityId": 1,
"permissions": _permissionPage.selectedGroups().map((group) {
return {
"groupId": group.id,
"permission": 1,
};
}).toList(),
}
});
Any idea? Can't find anything on google.
Love to see the community that is created around the graphql_flutter library.
class DiaryGroupPermission {
int groupId;
int permission;
DiaryGroupPermission.fromJson(Map json)
: groupId = json['groupId'],
permission = json['permission'];
}
class DiaryInsideCommunity {
int communityId;
List<DiaryGroupPermission> permissions;
DiaryInsideCommunity.fromJson(Map json)
: communityId = json['communityId'],
permissions = json['permissions']
.map<DiaryGroupPermission>((Map permisionJson) =>
DiaryGroupPermission.fromJson(permisionJson))
.toList();
}
class Diary {
String body;
Diary(dynamic value) : body = value.toString();
}
typedef Diary createDiaryFunction(
DiaryInsideCommunity community, String description, String title);
DiaryInsideCommunity community = DiaryInsideCommunity.fromJson({
'communityId': 1,
'permissions': [
{'groupId': 1, 'permission': 1}
]
});
Diary mutation(DiaryInsideCommunity community,
{String description, #required String title}) =>
Diary(community.permissions[0].groupId);
Diary mutationResult = mutation(community, description: "a", title: "b");
I implemented the types that you wanted to in dart and created a mockup mutation function to show you how to call it.
There is no easier way to do types in dart.
Cheers from the creator of this library,
Eus
Assuming you are using graphql_flutter,
You may specify it in variables
an example is say you have this definitions for a mutation
type Mutation {
createMeterReading(
createMeterReadingInput: CreateMeterReadingInput
): MeterReading }
your input type definition
input CreateMeterReadingInput {
reading: Float
companyId: Int
companyStaffId: Int
customerId: Int
readingDataType: String
latitude: Float
longitude: Float
masterMeterId: Int
analogMeterId: Int
type: String
editedStatus: String
base64Image: String
readingTime: String
}
In flutter have
final response = await client.value.mutate(MutationOptions(
variables: {
'createMeterReadingInput': {
'reading': double.parse(_meterReadingController.text),
'companyStaffId': _decodedToken["companyStaffId"],
'analogMeterId': waterMeter["analogMeterId"],
'type': "actual",
'base64Image': getBase64(),
'readingTime': timeNow,
'latitude': widget?.currentPosition?.latitude,
'longitude': widget?.currentPosition?.longitude
}
},
documentNode: gql(r"""
mutation createMeterReading($createMeterReadingInput:CreateMeterReadingInput ) {
createMeterReading(createMeterReadingInput: $createMeterReadingInput) {
meterReadingId
reading
companyId
companyStaffId
imageUrl
editedStatus
companyStaff{
firstName
}
}
}
"""),
));