HHVM extension, How to return class - hhvm

I declare method as Variant:
Variant HHVM_METHOD(MyClass1, get) {
Object ob;
ob.o_set(s_PropertyName1, value1, s_MyClass2 );
ob.o_set(s_PropertyName1, value2, s_MyClass2 );
return Variant(ob);
}
PHP code:
$c = new MyClass1();
var_dump($c->get()); // return StdClass
How to create and return MyClass2:
var_dump($c->get()); // must return MyClass2

When creating the Object, you need to pass in a pointer to the Class object.
Variant HHVM_METHOD(MyClass1, get) {
Object ob{Unit::loadClass(s_MyClass2.get()};
ob.o_set(s_PropertyName1, value1, s_MyClass2 );
ob.o_set(s_PropertyName1, value2, s_MyClass2 );
return ob;
}
You can see this being used in DateTime::createFromFormat

Related

Change how map keys are checked for equality

I have the following code:
class KeyClass {
int property;
KeyClass(this.property);
}
void main() {
KeyClass kc1 = KeyClass(1);
KeyClass kc2 = KeyClass(2);
Map<KeyClass, String> map = Map();
map[kc1] = 'hello';
map[kc2] = 'world';
...
}
My goal is to for the following two lines to get the same value from my map:
print(map[kc1]); // prints 'hello'
print(map[KeyClass(1)]); // prints 'null', should print 'hello' too!
Is this possible in Dart language?
The default Map implementation is a LinkedHashMap, so it relies on computing hash codes for the keys. There are a few ways you could make your keys compare equal:
Implement KeyClass.operator == and KeyCode.hashCode:
class KeyClass {
int property;
KeyClass(this.property);
bool operator ==(dynamic other) {
return runtimeType == other.runtimeType && property == other.property;
}
int get hashCode => property.hashCode;
}
Use LinkedHashMap directly. LinkedHashMap's constructor allows providing custom callbacks for computing equality and hash codes:
bool keyEquals(KeyClass k1, KeyClass k2) => k1.property == k2.property;
int keyHashCode(KeyClass k) => k.property.hashCode;
Map<KeyClass, String> map = LinkedHashMap<KeyClass, String>(
equals: keyEquals,
hashCode: keyHashCode,
);

How to find an element in a dart list

I have a dart list of objects, every of which contains book_id property, and I want to find an element of that list by the book_id field.
Use firstWhere method: https://api.flutter.dev/flutter/dart-core/Iterable/firstWhere.html
void main() {
final list = List<Book>.generate(10, (id) => Book(id));
Book findBook(int id) => list.firstWhere((book) => book.id == id);
print(findBook(2).name);
print(findBook(4).name);
print(findBook(6).name);
}
class Book{
final int id;
String get name => "Book$id";
Book(this.id);
}
/*
Output:
Book2
Book4
Book6
*/
Null-Safe approach (handling no-element error)
If the searched item might or might not be in the array, with null safety I personally prefer to use .where on lists - it filters through the array and returns a list.
var myListFiltered = myList.where((e) => e.id == id);
if (myListFiltered.length > 0) {
// Do stuff with myListFiltered.first
} else {
// Element is not found
}
The benefit of this approach is that you'll always get an array and there won't be an issue with element not being found or trying to return null through orElse callback:
The return type 'Null' isn't a 'FooBar', as required by the closure's context.
Refactoring the finder logic into a helper method
Since the task of finding an element by id in a list of objects is quite a common one, I like to extract that logic into helpers file, for example:
class Helpers {
static findById(list, String id) {
var findById = (obj) => obj.id == id;
var result = list.where(findById);
return result.length > 0 ? result.first : null;
}
}
And use it like this:
var obj = Helpers.findById(myList, id);
if (obj == null) return; //? Exn: element is not found
A lot has been said already, but I want to add my best way to do this. if it's possible that the item doesn't exist in the list, import the iterable extension and use firstWhereOrNull1 on the list.
import 'package:collection/src/iterable_extensions.dart';
myList.firstWhereOrNull((item) => item.id == id))
You should add orElse to avoid exeption:
list.firstWhere(
(book) => book.id == id,
orElse: () => null,
});
To avoid having to add orElse to every use of firstWhere, with Dart 2.7+, you can create a handy little extension to handle this:
extension IterableX<T> on Iterable<T> {
T safeFirstWhere(bool Function(T) test) {
final sublist = where(test);
return sublist.isEmpty ? null : sublist.first;
}
}
Which can then be used as such:
final books = List<Book>.generate(10, (id) => Book(id));
final matchingBooks = books.safeFirstWhere((book) => book.id == id);
void main(){
List lights=[
{"id":1,"color":"yellow"},
{"id":2,"color":"green"},
{"id":3,"color":"red"}
];
int searchId = 2;
var colr = lights.firstWhere((x) => x['id'] == searchId, orElse:() => {"color" : "Color Not found"})['color'];
print(colr);
}
The above code searches the obj list, using firstWhere. If not found returns text 'Color not found'

Limit a generic type argument only to be a int, double or custom class

I trying make the following code but T only can be int, double or a custom class. I couldn't find how to restrict the type in Dart or something that work like where from C#. How can I do that in Dart?
class Array3dG<T> extends ListBase<T> {
List<T> l = List<T>();
Array3dG(List<T> list) {
l = list;
}
set length(int newLength) { l.length = newLength; }
int get length => l.length;
T operator [](int index) => l[index];
void operator []=(int index, T value) { l[index] = value; }
}
There is no way to constrain the type variable at compile-time. You can only have one bound on a type variable, and the only bound satisfying both int and your custom class is Object.
As suggested by #Mattia, you can check at run-time and throw in the constructor if the type parameter is not one of the ones you supprt:
Array3dG(this.list) {
if (this is! Array3dG<int> &&
this is! Array3dG<double> &&
this is! Array3dG<MyClass>) {
throw ArgumentError('Unsupported element type $T');
}
}
This prevents creating an instance of something wrong, but doesn't catch it at compile-time.
Another option is to have factory methods instead of constructors:
class Array3dG<T> {
List<T> list;
Array3dG._(this.list);
static Array3dG<int> fromInt(List<int> list) => Array3dG<int>._(list);
static Array3dG<int> fromDouble(List<double> list) => Array3dG<double>._(list);
static Array3dG<MyClass> fromMyClass(List<MyClass> list) => Array3dG<MyClass>._(list);
...
}
which you then use as Array3dG.fromInt(listOfInt). It looks like a named constructor, but it is just a static factory method (so no using new in front).
You can check at runtime the type with the is keyword:
Array3dG(List<T> list) {
if (list is List<int>) {
//Handle int
}
else if (list is List<double>) {
//Handle double
}
else if (list is List<MyClass>) {
//Handle MyClass
}
else {
throw ArgumentError('Unsupported $T type');
}
}
Note that if you are handling int and double in the same way you can just check for num
You can check the progress of the Union types here: https://github.com/dart-lang/sdk/issues/4938

Can I use generics in Dart like this?

I want to parse http response to Dart object,so I defined a abstract class
BaseBean:
abstract class BaseBean{
BaseBean.fromJson(Map<String, dynamic> json);
Map<String, dynamic> toJson();
}
And I used it in a function:
Future<ResultData<T>> netFetch<T extends BaseBean>(){
......
return new ResultData(T.fromJson(), result, code);
}
but T.fromJson() has an error:
The method 'fromJson' isn't defined for the class 'Type'
So,can I use generics in Dart like this?Is there a better way to solve this problem?
Yes, of course, it is possible, but only with a workaround:
T unmarshal<T>(Map map, {Type type}) {
if (type == null) {
type = T;
}
switch (type) {
case Order:
return Order.fromJson(map) as T;
case OrderItem:
return OrderItem.fromJson(map) as T;
case Product:
return Product.fromJson(map) as T;
default:
throw StateError('Unable to unmarshal value of type \'$type\'');
}
}
var order = unmarshal<Order>(data);
//
var product = unmarshal(data, type: Product) as Product;
//
var type = <String, Type>{};
types['OrderItem'] = OrderItem;
// ...
var type = types['OrderItem'];
var orderItem = unmarshal(data, type: type);
I used the same approach and I came to this solution.
I created a Map<Type, BaseBean Function(dynamic)> decoders.
It looks like
final decoders = {
MyClass: (data) => MyClass.fromJson(data),
};
and I get the function in this way
final MyClass myData = decoders[T]!(data);
You can also create a typedef for the BaseBean Function(dynamic) like this
typedef Decoder = BaseBean Function(dynamic);
So the Map<Type, BaseBean Function(dynamic)> will became Map<Type, Decoder>.

in Dart, given a Type name, how do you get the Type (class) itself? [duplicate]

This question already has answers here:
Create an instance of an object from a String in Dart?
(3 answers)
Closed 8 years ago.
if have a Type, using Mirrors can get the Type name. inversely, given a Type's name, how do you get the Type?
for example, from a Dart-centric version of Angular:
index.html
<form ng-controller='word?reset=true' >
...
</form>
mylib.dart
class Controller {
Controller( Brando brando, Element elem, Map args ) { ... }
}
class Word extends Controller { ... }
class LangList extends Controller { ... }
// Brando, the godfather
class Brando {
...
void compile( Element el ) {
...
// add controller
if( el.attributes.contains( 'ng-controller' ) {
var name = el.attributes.getTypeName(); <== "Word"
var args = el.attributes.getTypeArgs(); <== { 'reset': 'true' }
var type = <get type from camelized Type name> <=== how??
this.controllers.add( reflectClass(type).newInstance(
const Symbol(''), [this,el,args]).reflectee ); <=== instance from type
}
...
}
}
know how to get name of Type, how to get Type from class and Object, and know how to instantiate a Type. missing final piece - how do you derive the Type from its name?
Note: The mirror API is `unstable', so this answer may change over time.
*Note: This may (will) bloat your generated javascript see: https://api.dartlang.org/docs/channels/stable/latest/dart_mirrors/MirrorSystem.html#getSymbol*
import 'dart:mirrors';
class Bar {
}
ClassMirror findClassMirror(String name) {
for (var lib in currentMirrorSystem().libraries.values) {
var mirror = lib.declarations[MirrorSystem.getSymbol(name)];
if (mirror != null) return mirror;
}
throw new ArgumentError("Class $name does not exist");
}
void main() {
ClassMirror mirror = findClassMirror("Bar");
print("mirror: $mirror");
}
output:
mirror: ClassMirror on 'Bar'

Resources