class A {}
class B extends A {}
the code above work fine but when I try to do the same with an imported class, I't does not work.
declare module 'a' {
declare export class A {}
}
import typeof { A } from 'a';
class B extends A {}
Cannot reference type A [1] from a value position
can anyone solve this ?
https://flow.org/try/#0CYUwxgNghgTiAEBbA9sArhBByKX4G8AoeeUSWBEADwAdkYAXecgZxfgEECBfQ3wgJaI6jeAwCeNEMgBmBTvG4ACmTGSJ4OLAG5ChVuwBC8agxAA7YOy75uQA
When you define a class you actually define both a type and a Javascript class, and both have the same name. Types only exist at compile time - they have no runtime representation. In your example you imported the type, but not the runtime value.
// imports the type only
import typeof { A } from 'a'
// imports both the type and the runtime value
import { A } from 'a'
The type informs Flow what the class does for purposes of type checking. But the runtime value is what defines the implementation to be executed. The compiled program must have a reference to the runtime value to instantiate or to extend a class. In other words, remove the typeof keyword and it should work.
Related
In some code I am reading, I see a class declared thus:
export abstract class ClassName<T = unknown> implements InterfaceName { … }
I am familiar with unconstrained generics (class C<T> {…) and constrained generics (class C<T extends S> {…), but what does = unknown mean, and what effect does it have compared to no constraint at all?
Surely, absent an extends, code within the generic class must treat T as if it were unknown already? And if <T = S> means to pin type T to exactly type S then why make it a generic at all?
This is default parameter type. It is type, that is resolved, when the type constructor is given without the type parameters.
Consider this class definition:
export class Class<T = unknown> { }
Then you can create instances either with explicit type for T or without.
const x = new Class()
const y = new Class<unknown>()
const z = new Class<number>()
Here, type of x and y will both be Class<unknown>, whereas z would be Class<number>. So it means, that declaring class with <T = unknown> is the same as <T>.
So for this particular case, it doesn't make much sense, but if you choose anything else than unknown, then it will serve as default type parameter.
Note, that it doesn't serve as constraint, that means that if you declare
export class ClassB<T = string> { }
you can still declare:
const z = new ClassB<number>()
It appears that class types in flow always refer to instances of that class and one uses typeof to refer to the actual class itself. So, if I want a variable to refer to a subclass (not an instance) of a base class, I can do:
class MyBaseClass {}
class MySubClass extends MyBaseClass {}
let a: $Subtype<MyBaseClass> = MySubClass; // fails
let b: $Subtype<MyBaseClass> = new MySubClass(); // works, but I don't want this.
let c: $Subtype<typeof MyBaseClass> = MySubClass; // works! Ok, we're good
However, I can't seem to do this with type parameters! For example, the following:
type GenericSubclass<T> = $Subtype<typeof T>;
// fails with `^ identifier `T`. Could not resolve name`
If I try the following Typescript trick (see Generic and typeof T in the parameters), it also fails:
type ValidSubclass<T> = { new(): T };
const c: ValidSubclass<BaseClass> = MySubClass;
// fails with: property `new`. Property not found in statics of MySubClass
Note that I tried new, __proto__ and constructor.
What gives? Is there a workaround?
typeof MyBaseClass
is
Class<MyBaseClass>
so you can do
type GenericSubclass<T> = $Subtype<Class<T>>;
I have a Kotlin class whose primary (and only) constructor is empty.
I have a reference to this class:
val kClass: KClass<MyClass> = MyClass::class
How do I create an instance of this class using reflection?
In Java I would do myClass.newInstance() but it seems in Kotlin I need to find the constructor first:
kClass.constructors.first().call()
I have seen mention of primaryConstructor in some bug reports but it's not showing up in my IDE.
In your case, Java reflection might be enough: you can use MyClass::class.java and create a new instance in the same way as you would with Java reflection (see #IngoKegel's answer).
But in case there's more than one constructor and you really need to get the primary one (not the default no-arg one), use the primaryConstructor extension function of a KClass<T>. It is a part of Kotlin reflection, which is not shipped within kotlin-stdlib.
To use it, you have to add kotlin-reflect as a dependency, e.g. a in Gradle project:
dependencies {
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
}
Assuming that there is ext.kotlin_version, otherwise replace $kotlin_version with the version you use.
Then you will be able to use primaryConstructor, for example:
fun <T : Any> construct(kClass: KClass<T>): T? {
val ctor = kClass.primaryConstructor
return if (ctor != null && ctor.parameters.isEmpty())
ctor.call() else
null
}
You can use the Java class to create new instance:
MyClass::class.java.newInstance()
For those checking this question now, since Kotlin 1.1 there's also createInstance() extension method on KClass
Much like the accepted answer, this function works only in case class has an empty constructor or constructor with all default arguments.
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect.full/create-instance.html
Expanding on Alexeys Answer, to include a primary constructor call with parameters:
/* Example class with no-args constructor */
class MyClass
/* Example class requiring parameters */
class MyClassWithParams(parameter1: String, parameter2: MyClass)
val myKClass: KClass<MyClass> = MyClass::class
val myKClassWithParameters: KClass<MyClassWithParams> = MyClassWithParams::class
/* We can create an object by calling createInstance when no constructor parameters are required as explained in other answers. */
val myObject: MyClass = myKClass.createInstance()
/* To create an object with parameters, we need to get the constructor first, and call it with the parameters instead, similarly to how we would do in Java. */
val myObjectWithParameters: MyClassWithParams? =
myKClassWithParameters.primaryConstructor?.call(
"StringParameter", myObject
)
I'm trying to use macro annotations in scala, where my macro annotation would take an argument of another type. It would then use scala reflection to look at the passed in type, and add some methods as appropriate.Eg.
trait MyTrait {
def x: Int
def y: Float
}
#MyAnnotation class MyClass //<-- somehow, this annotation should reference MyTrait
class MyAnnotation(val target: Any) extends StaticAnnotation {
def macroTransform(annottees: Any*) = macro MyAnnotationImpl.impl
}
object MyAnnotationImpl {
def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
// if I can get a handle on the type MyTrait in here
// then I can call .members on it, etc.
...
}
}
Basically, the same thing as Using Scala reflection in Scala macros, except using macro annotations. However, when I try to template my macro annotation with a TypeTag
class MyAnnotation[T](val target: Any) extends StaticAnnotation {
def macroTransform[T](annottees: Any*) = macro MyAnnotationImpl.impl[T]
}
object MyAnnotationImpl {
def impl[T: c.WeakTypeTag](c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
...
}
}
I get
[error] /Users/imran/other_projs/learn_macros/macros/src/main/scala/com/imranrashid/oleander/macros/MacrosWithReflection.scala:7: macro annotation has wrong shape:
[error] required: def macroTransform(annottees: Any*) = macro ...
[error] found : def macroTransform[T](annottees: Any*) = macro ...
[error] class MyAnnotation[T](val target: Any) extends StaticAnnotation {
[error] ^
I've also tried to make the type an argument to my annotation, so I would use it like #MyAnnotation(MyTrait) class Foo .... I can extract the name as a String with something like
val targetTrait = c.prefix.tree match {
case Apply(Select(New(Ident(_)), nme.CONSTRUCTOR), List(Ident(termName))) => termName
}
but, I'm not sure what I can do w/ that String to get back the full type. I've also tried variants like #MyAnnotation(typeOf[MyTrait]) class Foo ..., and then use c.eval on the typeOf inside my macro, but that doesn't compile either.
In macro paradise 2.0.0-SNAPSHOT we have quite a tricky way of accessing type parameters for macro annotations (the situation will improve later on when we have dedicated APIs for that, but right now it's very difficult to introduce new functionality to scala-reflect.jar in macro paradise, so the current API is a bit rough).
For now it's necessary to specify the type parameter on the annotation class and not to declare any type parameters on the macroTransform method. Then, in macro expansion, access c.macroApplication and extract the untyped tree corresponding to the passed type parameter. Afterwards, do c.typeCheck as described in Can't access Parent's Members while dealing with Macro Annotations.
As Eugene points out in his answer it is possible to match on the tree of the whole macro application. Like every Scala method, annotation macro applications can take multiple type argument lists as well as multiple value argument lists.
Consider the macro application of an annotation macro called test:
#test[A, B][C, D](a, b)(c, d) trait Foo
In the implementation of test we can inspect the macro application by
println(show(c.macroApplication))
which will result in:
new test[A, B][C, D](a, b)(c, d).macroTransform(abstract trait Foo extends scala.AnyRef)
To extract the (type/value) parameters from the tree you have to pattern match on the tree. A parser for an arbitrary amount of parameter lists can be found in this project
Using this parser retrieving the first value argument of the macro application is as easy as
val List(List(arg)) = MacroApp(c.macroApplication).termArgs
i want make own flex library and in this library use own actionscript file which will i use in more component in this library..this file contents eg only code
public function computeSum(a:Number, b:Number):Number {
return a + b;
}
but when i can this create just when i click File-New-Actionscript File (filename - OK) is in Problem view Error: A file found in a source-path must have an externally visible definition. If a definition in the file is meant to be externally visible, please put the definition in a package
thanks for help
You should encapsulate it on class, in order to use it with import directive, else u could use it with include
Another approach is to create a "helper" class, or so called "singleton" class.
- a class having only 1 instance, created statically.
on this class u can expose the library functions which u do need and use them everywhere.
package
{
public class Singleton
{
private static var singleton : Singleton
public static function getInstance() : Singleton
{
if ( singleton == null )
singleton = new Singleton();
return singleton;
}
public function Singleton()
{
}
public function visibleTroughtTheSingletonfunction( arg1 : int ... ) : void
{
}
public static function directlyVisiable() : void
{
}
}
}
the accessing the singleton would be something like :
Singleton.getInstance.visibleTroughtTheSingletonfunction( 1 );
OR
Singleton.directlyVisiable();
depending on your needs.
Well first you'll need to create a class (and a package) and put that method inside that (not just into an empty AS file) and second if you want to be able to access the method without creating an instance of the class make this method static.
If you don't need to change the class file during runtime then make action class compile into swc library.
create a Action script project and compile it in the bin folder you found the .swc library file. include that .swc into your project .