How to get the original types of the properties of a reflected class? - dart

After trying several ways to get to know about the original types of the classproperties from a reflected class.
For example, this is an Animator class and Animator has four properties with it (id, name, costPerHour and reviews)
class Animator {
int id;
String name;
double costPerHour;
List<Review> reviews;
}
...And from the Animator class, I wanna loop through the properties and I also wanna know if for example
the original type of id (is id an int, a String or an object?).
With the discovery that declarations doesn't give the needed information in this situation;
var _refClass = reflectClass(Animator);
var classProperties = _refClass.declarations.values.forEach((property) => {
// property.runtimeType returns only _DeclarationMirror of _propertyname_
}); // What is the original type each property??
Help is really appreceated, thanks.

Related

Is there a way to access a mixin's private variable in the class using the mixin?

In dart when creating a mixin, you can declare properties and methods like a class. When declaring a private property/method, it seems the inheriting class should also have access to this private member (see below for example).
Is there a way to access a mixin's private variable in the class using the mixin?
If it's not possible, how can I declare a member in the mixin object but make it private in the inheriting class's interface.
mixin.dart
mixin A {
String propertyOne = '1';
// This property is not accessible to any inheriting class.
int _privateProperty = 2;
}
class.dart
class B with A {
String get mixinString => propertyOne;
// This property is not accessible to the B class.
int get mixinInt => _privateProperty;
}
No. A property being library private means that you can only express its name inside the same library. In any other library, the identifier _privateProperty is a different name, one private to that other library.
If you cannot declare both mixin and class in the same library, and you definitely need access to the property, then you can do any number of things to allow that.
Make the property public and tell people not to use it except in subclasses. They still can if they want to.
Make the property public and mark it #protected, to have the analyzer tell people to not use it except in subclasses. They still can if they want to.
Keep the property private and provide a separate method to access it:
mixin A {
// This property is not accessible to any inheriting class.
int _privateProperty = 2;
static int getPrivateProperty(A a) => a._privateProperty;
static void setPrivateProperty(A a, int value) {
a._privateProperty = value;
}
}
Anyone can still get to the property if they really want to, but they need to know that
it comes from A.

Aqueduct ORM ManagedObject's transient property being persisted

I have an Aqueduct project using the ORM, with a data model as follows:
class _Thing {
#primaryKey
int id;
String first;
String second;
}
class Thing extends ManagedObject<_Thing> implements _Thing {
#Serialize()
OtherThing get firstAndSecond() {
// return some value computed from first and second
}
#Serialize()
set firstAndSecond(OtherThing firstAndSecond) {
// set first and second based on some computation
}
}
According to the docs for transient properties, annotating with #Serialize() should enable this model to be serialized/deserialized. It also says that properties in ManagedObjects are not persisted, but when I run the server, I get the error:
Data Model Error: Property 'firstAndSecond' on 'Thing' has an unsupported type.
If I remove the #Serialize(), it doesn't try to persist it, but I can't serialize/deserialize this object.
Any suggestions as to why this is happening or how I can control this behaviour?
This should be in the docs -
A Serializable property must be a primitive type (e.g. String, int, double, bool or a Map or List containing these types). Serializable values are passed directly to the codec that is reading from a request body or writing to a response body (by default, this codec is JSON). In the case of a custom type like OtherThing, the codec doesn't know how to encode or decode that type.
For complex types, you might use a map:
#Serialize()
Map<String, dynanic> get firstAndSecond() {
return {"first": first, "second": second};
}
You might also use CSV-like data:
#Serialize()
String get firstAndSecond() {
return "$first,$second";
}

How to clone (copy values) a complex object in Dart 2

I would like to clone a complex object (copy values), not referencing, using Dart 2.
Example:
class Person {
String name;
String surname;
City city;
}
class City {
String name;
String state;
}
main List<String> args {
City c1 = new City()..name = 'Blum'..state = 'SC';
Person p1 = new Person()..name = 'John'..surname = 'Xuebl'..city = c1;
Person p2 = // HERE, to clone/copy values... Something similar to p1.clone();
}
What would be the way (best practice) to do this?
Update note: This How can I clone an Object (deep copy) in Dart? was posted some time ago. The focus here is to understand if Dart 2 that is bringing many improvements, has a facility for copying complex objects.
With the classes you have shown us here, there is nothing shorter than
Person p2 = Person()
..name = p1.name
..surname = p1.surname
..city = (City()..name = p1.city.name..state = p1.city.state);
If you add a clone method to Person and City, then you can obviously use that.
There is nothing built in to the language to allow you to copy the state of an object.
I would recommend changing the classes, at least by adding a constructor:
class Person {
String name;
String surname;
City city;
Person(this.name, this.surname, this.city);
}
class City {
String name;
String state;
City(this.name, this.state);
}
Then you can clone by just writing:
Person P2 = Person(p1.name, p1.surname, City(p1.city.name, p1.city.state));
(And ob-link about names)
I say that there is no language feature to copy objects, but there actually is, if you have access to the dart:isolate library: Sending the object over a isolate communication port. I cannot recommend using that feature, but it's here for completeness:
import "dart:isolate";
Future<T> clone<T>(T object) {
var c = Completer<T>();
var port = RawReceivePort();
port.handler = (Object o) {
port.close();
c.complete(o);
}
return c.future;
}
Again, I cannot recommend using this approach.
It would work for simple objects like this, but it doesn't work for all objects (not all objects can be sent over a communication port, e.g., first-class functions or any object containing a first class function).
Write your classes to support the operations you need on them, that includes copying.
My simpler solution just let clone() return a new Person with the current values:
class Person {
String name;
String surname;
City city;
Person(this.name, this.surname, this.city);
clone() => Person(name, surname, city);
}
You might further need to recursively clone the objects in your Person. as an example by creating a similar clone() function in the City and using it here as city.clone().
For the strings you will need to check their behavior or also create / add a way for cleaning them.
As said, there is no built in solution for that, but if the ideia is to accomplish immutable value types you can check built_value.
https://medium.com/dartlang/darts-built-value-for-immutable-object-models-83e2497922d4
I noted that using Map.from() do a shallow copy and not a deep copy.
To do a deep copy of a class containing a Map of anoter Class, one solution can be to use a nammed constructor
class MyClassB {
int myVar;
// Constructor
MyClassB(this.id);
// Named Constructor to do a deep clone
MyClassB.clone(MyClassB b){
id = b.id;
}
}
class MyClassA {
Map<int,MyClassB> mapOfClassB;
// Constructor
MyClassA(this.myClassB)
// Named constructor to do a deep clone
MyClassA.clone(MyClassA a){
Map<int,myClassB> m = {};
myClassB = a.mapOfClassB.forEach((k,v)=> m[k] = MyClassB.clone(v)); // Use the clone constructor here, if not the maps in MyClassA and MyClassB will be linked
}
}
main() {
var b1 = MyClassB(20);
var a1 = MyClassA({0:b1});
var a2 = MyClass1A.clone(a1);
a2.mapOfClassB[0].id = 50;
print(a1.mapOfClassB[0].id); // Should display 20
print(a2.(a1.mapOfClassB[0].id) // Should display 50
}
Using a package like freezed, you could make deep copies of the complex objects.
Although one downside is that the objects are immutable and you cannot make shallow copies of it. But again, it depends on your use case and how you want your objects to be.

How to use generics in own created model class in iOS?

How to use generics in own created model class?
I have one FeatureListModel class and other have FavoriteModel class. Both store the same properties, the only difference is the different class model name.
I need to display model properties value in ProductDetail controller.
How could I manage this stuff using generics?
Here is my code (Swift 4.2):
1st Model: FavoriteListModel
class FavoriteListModel {
var categoryID: Int?
var item_name: String?
var MRP: String?
}
2nd Model: FeatureListModel
class FeatureListModel {
var categoryID: Int?
var item_name: String?
var MRP: String?
}
I have 8-10 more properties, but this is just some stuff in my code.
Controller - ProductDetailTableViewController
class ProductDetailTableViewController : UITableViewController {
var productDetails: FavoriteListModel!
var productFeatureList: FeatureListModel!
fileprivate func displayProduct() {
if productDetails != nil {
title = productDetails.item_name
categoryID = productDetails.categoryID!
}else if productFeatureList != nil {
categoryID = productFeatureList.categoryID!
title = productFeatureList.item_name
}
}
and in my Product Detail Table Controller, I am accessing model objects and display on the screen.
I don't want if-else check.
You are mixing up generics and protocols. In your case a protocol is preferable.
In ProductDetailTableViewController there is an object which responds to the getter of item_name (by the way please conform to the camelCased naming convention itemName) and categoryID. The type of the object as well as the existence of other properties and functions is not significant.
Create a protocol
protocol Listable {
var itemName : String { get }
var categoryID : Int { get }
}
Then adopt the protocol in your classes (do you really need a class?) and declare at least categoryID as non-optional since you are force unwrapping the value later anyway. Don't use optionals as an alibi not to write an initializer.
class FavoriteListModel : Listable { ...
class FeatureListModel : Listable { ...
In ProductDetailTableViewController rather than two properties declare one property as Listable and instead of objective-c-ish nil checking use optional binding:
var details: Listable!
fileprivate func displayProduct() {
if let productDetails = details {
title = productDetails.itemName
categoryID = productDetails.categoryID
}
}
What you have here is not a use case for the Generics. Generics are used when you have for example a function that does exact same thing but can be used with two different parameter types. That's when you use generics.
Another concept is super class (parent class or base class) which is used when you have a class with common properties and then other classes with those properties and then extra and different unique properties which in this case, each class subclasses the parent class.
What you have here is neither of them. A good architecture for this case is just a single model type (class or struct) and using two different collections (array or set) in your view controller.
You can also create a favorite class or featured class which holds an array with your models.

Get and Set on each field like in Java

I tried to look all over the internet to find out what is the best practice of encapsulating data in Swift. I only found some information about get and set method of an instance variables. They used to work pretty much like C#'s did set, but now they work as computed properties and one can't set them in their setters and can't get them in their getters. The question is: do people still create getter and setter for each property in the class in swift ? Like:
private var age: Int = 0
public func getAge() -> Int {
return age
}
public func setAge(newAge: Int) {
self.age = newAge
}
If not, then what is considered to be the best practice ?
Thank You.
I use this type of syntax with computed vars to expose the getter and setters when the internals are more complex than what is shown here:
internal var _age: Int = 0
var age: Int {
get {
return _age
}
set {
_age = newValue
}
}
Plenty of syntaxic sugar to make it easy to hide complexity in some expressions.
But most of the time I am happy with just exposing the plain var and be done with it:
var age: Int = 0
The advantage of this is that both ways are easily swappable when you want to do more work inside the getters and setters.
I don't think you need to create getX/setX methods, because you can always change from a stored to a computed property without having to change the source code of the clients. Just like you could change the bodies of your getAge & setAge methods, so I do not see what is gained in swift by not letting clients use age.
if you want to access the property (Age) itself, you can always get/set it directly.
let theGirlsAge = Age; // Get
Age = theBoysAge; // Set
Getters and Setters are used for define relationship between the property and other properties.
public func getAge() -> Int {
return theBoysAge
}
public func setAge(newAge: Int) {
theGirlsAge = newAge
}

Resources