interface Squel<S extends Select = Select,
U extends Update = Update,
D extends Delete = Delete,
I extends Insert = Insert,
C extends Case = Case> {
I cannot understand the assignment after extends. Could someone explain it? I do not find in Typescript official document.
These are generic parameter defaults. They work similarly to default values for regular function parameters.
They allow you to not provide type arguments for type parameters.
let squel: Squel/*< no need to pass type arguments, yay! >*/
And if your type was like this:
interface Squel<S extends Select,
U extends Update,
D extends Delete,
I extends Insert,
C extends Case>
Then you would have to always pass type arguments:
let squel: Squel<Select, Update, Delete, Insert, Case>
^^^ this part is mandatory now ^^^
P.S. The typescript handbook seems to not have information about this feature, but 2.3 release does have it (scroll to Generic parameter defaults)
Related
Consider class with type parameter, that should be used as Map key.
class Foo<K> {
var map: Map<K, Dynamic> = new Map();
}
This does not compile with error Type parameters of multi type abstracts must be known.
The reason is understandable - Map is abstract and it's underlying type is selected based on key type, so key type should be known when compiling new Map() expression. On the other hand non-generic type with type parameters are compiled once for all parameters.
Looks like adding #:generic metadata should help. But actually it does not. My guess was that this is because haxe compiler compiles #:generic types the same as it does with non-generic types, and only then does some extra work for generic type. So I was thinking that having a Map with key type defined by type parameter is impossible in haxe.
But recently I've stumbled upon this issue: https://github.com/HaxeFoundation/haxe/issues/2537
Simn's answer there says, that this can be done by adding #:remove #:generic metadata. And it actually works.
#:remove #:generic
class Foo<K> {
var map: Map<K, Dynamic> = new Map();
}
For me this looks like magic and I'm not comfortable with this. In documentation I only see that
#:remove Causes an interface to be removed from all implementing classes before generation. That does not explain why this works.
If you replace Map by haxe.ds.BalancedTree and use only #:generic without #:remove, you will see your class Foo generated on your target containing new BalancedTree< object, object > (object is Dynamic). That means, Foo class holds general BalancedTree< object, object > type, while Foo_String for example holds generic BalancedTree< string, object > type. Now, if you go back to your Map, you will see that "Abstract haxe.ds.Map has no #:to function that accepts haxe.IMap< Foo.K, Dynamic >", e.g. no Map< Dynamic, Dynamic > implementation exists. That's why you need to use #:remove which will actually stop generation of Foo class, or at least, remove new Map< Dynamic, Dynamic > from the Foo (#:remove "Causes an interface to be removed" is misleading here)
When I want to make cross referencing between grammar rules in Xtext work, I need to use keyword name for that. E.g.:
Constant:
name=NAME_TERMINAL "=" number=Number;
ConstUsage:
constant=[Constant | NAME_TERMINAL];
Is it possible to change this word to another one (e.g. id) ? I need it e.g. in case when I have rule, which uses parameter name for something else.
you can use a custom implementation of IQualifiedNameProvider e.g. by subclassing DefaultDeclarativeQualifiedNameProvider.
public class MyDslQNP extends DefaultDeclarativeQualifiedNameProvider{
QualifiedName qualifiedName(Element e) {
Package p = (Package) e.eContainer();
return QualifiedName.create(p.getName(), e.getId());
}
}
see https://dietrich-it.de/xtext/2011/07/16/iqualifiednameproviders-in-xtext-2-0.html for the complete example
I am using Nomin for mapping tasks. As taken from the documentation of Nomin it should be able to map fields with the same name by itself in case automapping has been activated. When activating it, it causes an infinite loop exception.
I have the following:
mappingFor a: CoinsOnMarketPlace, b: Coin
// automap() // when deactivated it works fine, when activated infinite loop
a.coin.name = b.name
a.coin.rank = b.rank
a.priceUSD = b.priceUSD // Could be automapped
a.priceBTC = b.priceBTC // Could be automapped
...
Exception:
org.nomin.core.NominException: ./net/hemisoft/ccm/repository/coinmarketcap2coin.groovy: Recursive mapping rule a = b causes infinite loop!
One thing worth adding regarding your use case - this Recursive mapping rule a = b causes infinite loop! exception is thrown because you use groovy classes in your mapping rule. Nomin uses ReflectionIntrospector and what's important:
It performs getting/setting properties using accessor methods which are called through the Java reflection mechanism. ReflectionIntrospector uses supplied NamingPolicy instance to determine accessor methods. JbNamingPolicy is used by default, this implementation cerresponds the JavaBeans convention. Its InstanceCreator named ReflectionInstanceCreator instantiates objects using Class.newInstance().
Source: http://nomin.sourceforge.net/introspectors.html
A simple Groovy class like:
class Entity {
String name
String somethingElse
}
gets compiled to a Java class that implements GroovyObject providing following methods:
public interface GroovyObject {
Object invokeMethod(String var1, Object var2);
Object getProperty(String var1);
void setProperty(String var1, Object var2);
MetaClass getMetaClass();
void setMetaClass(MetaClass var1);
}
In this case ReflectionInstanceCreator combined with automap() resolves following mappings:
a.property = b.property
and
a = b
where a = b mapping comes from MetaClass getMetaClass() getter method I suppose, because there is no mapping like a.metaClass = b.metaClass resolved. a.property = b.property gets resolved because of Object getProperty(String var1) method.
Solution
This problem can be solved by specifying explicitly ExplodingIntrospector for your mapping script that:
It performs getting/setting properties using a class field immediately through through the Java reflection mechanism and may be useful in case when domain object don't provide accessors for their properties. Supplied instance creator is ReflectionInstanceCreator.
Source: http://nomin.sourceforge.net/introspectors.html
All you have to do is to add
introspector exploding
right below mappingFor a: ..., b: ... header. For example:
import mypackage.Entity
import mypackage.EntityDto
mappingFor a: Entity, b: EntityDto
introspector exploding
automap()
a.test2 = b.test1
Tested with two Groovy classes, worked like a charm. Hope it helps.
I'm getting ThisIsNotAObjectReference syntax message when trying to handle a fully typed data reference expression like this:
method getDataReference.
rr_value = ref #( varStructure ).
endmethod.
data(lr_value) = object->getDataReference( )->structureComponent.
I understand the syntax is identical for retrieving object references but how to deal with fully typed data references in expressions?
You cannot chain method calls with reference component accesses. You should use auxiliary variable like here:
CLASS lcl_class DEFINITION.
PUBLIC SECTION.
METHODS: getdatareference RETURNING VALUE(rr_value) TYPE REF TO mara.
ENDCLASS.
CLASS lcl_class IMPLEMENTATION.
METHOD getdatareference.
DATA: ls_mara TYPE mara.
rr_value = REF #( ls_mara ).
SELECT SINGLE * FROM mara INTO rr_value->*.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
DATA(lcl) = NEW lcl_class( ).
DATA(lv_mara) = lcl->getdatareference( ).
DATA(l_matnr) = lv_mara->matnr.
I'm kind of speculating about what you're trying to achieve here but as far as I know you'll need to dereference data reference before you can access their contents. The following extends the code you posted above.
report ztest.
class lcl_test definition.
public section.
methods getDataReference
returning value(rr_value) type ref to tadir.
private section.
data varStructure type tadir.
endclass.
class lcl_test implementation.
method getDataReference.
varstructure-author = sy-uname.
rr_value = ref #( varStructure ).
endmethod.
endclass.
start-of-selection.
data(object) = new lcl_test( ).
data(lr_value) = object->getDataReference( ).
field-symbols <structure> type tadir.
assign lr_value->* to <structure>. " This is the dereferencing step
write / <structure>-author.
Scenario:
I have x number of classes. Lets say 10; Each class does different UI Functions. When a user loads a file, that extension tells the program the classname to load; but it's in the form of a string.
Is there anyway to pass a string off as a classname? Something to the effect of.
var classname = "Booger";
var nose = new classname(){ //classname really means "Booger"
//Do Operation
}
You can reflect a type by name using var t = Type.from_name(classname);, however, this works on all types, including enums and structs and it might be the type Type.INVALID. You should probably do some checks, like t.is_a(typeof(MyParentClass)).
You can then instantiate a copy using var obj = Object.new(t);. The whole thing would look like:
var classname = "Booger";
var t = Type.from_name(classname);
if (t.is_a(typeof(MyParentClass)))
return Object.new(t);
else
return null;
It's also worth noting that the run-time type names have the namespace prepended, so you might want to do "MyNs" + classname. You can check in either the generated C or doing typeof(MyClass).name().
I've had the same problem as the OP in regards to getting an assertion error against null. If you take a look at the Glib documentation (in C) it mentions you have to register your class by actually specifying the class name first before you can actually use a string representation of your class name.
In other words you have to use your class first BEFORE you can instantiate a copy of your class with Glib.Type.from_name ("ClassName").
You can use your class first by instantiating a class instance or by getting type information for your class.
var type = typeof (MyClass);
var type_from_string = Type.from_name ("MyClass");
Furthermore, when you use Object.new to create a class there are two things you need to be aware of:
1) You need to cast the return value to get your specific class or base class.
var instance_of_my_class = Object.new (type) as MyClass;
2) Constructors for your class will no longer be called (I don't why). You will need to use the GObject style constructor inside your class:
construct {
pizza = 5;
}