Code:
contract A
{
uint public foo;
function A(uint _foo)
{
foo = _foo;
}
}
contract B
{
uint bar;
function B()
{
A a = new A(42);
bar = a.foo;
}
}
Compile Error
Test:18:15: Error: Type function () returns (uint256) is not implicitly convertible to expected type uint256.
bar = a.foo;
^---^
How can I read public variables of a contract in another?
contract A
{
uint public foo;
function A(uint _foo)
{
foo = _foo;
}
}
contract B
{
uint bar;
function B()
{
A a = new A(42);
bar = a.foo();
}
}
bar = a.foo(); instead of bar = a.foo; ...
Related
This is abstract contract in the context of Proxy pattern:
abstract contract Initializable {
bool private _initialized;
bool private _initializing;
modifier initializer() {
require(_initializing || !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
}
contract UpgradebleTest1 is Initializable {
uint public x;
function initialize(uint _x) public initializer {
x = _x;
}
}
I don't understand the necessity of _initializing and isTopLevelCall. Is not enough doing control using only _initialized?
Thanks,
The _initializing and isTopLevelCall combination allow for chained calls with the initializer modifier:
contract UpgradebleTest1 is Initializable {
uint public x;
function initialize(uint _x) public initializer {
internalInit(_x);
}
function internalInit(uint _x) internal initializer {
x = _x;
}
}
Without the _initializing and isTopLevelCall check, the initializer modifier would pass on the first call (initialize()) but fail on the second call (internalInit()).
modifier initializer() {
require(!_initialized, "Initializable: contract is already initialized");
_initialized = true;
}
abstract contract Initializable {
bool private _initialized;
modifier initializer() {
require(!_initialized, "Initializable: co...");
_;
_initialized = true;
}
}
contract UpgradebleTestParent is Initializable {
uint public x;
function initialize(uint _x) internal initializer {
x = _x;
}
}
contract UpgradebleTestMain is UpgradebleTestParent {
function init(uint _x) public initializer {
initialize(_x);
}
}
If it is as above, it would execute same logic, but _initialized = true; would be executed twice unnecessarily, right? However, it seems like cheaper than the previous one which has a one more variable and related additional instructions? Isn't it?
I know I can get the type of a method parameter by using "Method#parameters#name".
However, my parameters are all the subclass of A and I dont want to get the type A. I want to get the subclass name.
if (checkMethod(i)) {
val type = i.parameters[0].simpleName
if (!functions.containsKey(type)) {
functions[type] = HashMap()
}
if (!functions[type]?.containsKey(identifier)!!) {
functions[type]?.put(identifier, ArrayList())
}
functions[type]?.get(identifier)?.add(i)
}
Final Solution:
private fun analysis(clazz: KClass<EventHandler>, identifier: String) {
clazz.members.forEach {
if(it is KFunction) {
if(checkMethod(it)) {
val type = methodEventType(it)
if(!invokeMethods.containsKey(type)) invokeMethods[type] = HashMap()
if(!invokeMethods[type]!!.containsKey(identifier)) invokeMethods[type]!![identifier] = ArrayList()
invokeMethods[type]!![identifier]!!.add(it.javaMethod)
}
}
}
}
private fun checkMethod(method: KFunction<*>): Boolean {
method.annotations.forEach {
if(it is EventSubscriber) {
val type = method.parameters[1].type.classifier
if(type is KClass<*>) {
if(method.parameters.size == 2 && type.superclasses.contains(Event::class)) {
return true
}
}
}
}
return false
}
And notice here. I dont know why the method`s first parameter is allways a instance of its class. So the real parameter is start from 1 instead of 0.
Maybe you'll find this example useful (works with kotlin-reflect:1.4.21)
import kotlin.reflect.full.createType
import kotlin.reflect.full.isSubtypeOf
import kotlin.reflect.jvm.reflect
open class A
val aType = A::class.createType()
class B: A()
class C: A()
val foo = { b: B, c: C ->
println(b)
println(c)
}
println(foo.reflect()!!.parameters[0].type.classifier == B::class) // true
println(foo.reflect()!!.parameters[1].type.classifier == C::class) // true
println(foo.reflect()!!.parameters[0].type.isSubtypeOf(aType)) // true
To get all subclasses
println((foo.reflect()!!.parameters[0].type.classifier as KClass<*>).allSuperclasses.contains(A::class)) // true
Try this to get the class of the first parameter:
i.parameters[0]::class.java
i want declare a function that returns a common type or its extended type
interface Common {
id: number;
}
interface AdditionalInformation extends Common {
myname: string;
}
Surely the function returns an object containing the id property
and wishing it could also return the myname property
I tried to declare the function like this:
export class Lib {
public static lowestCommonDenominator <T extends Common>(): Common {
const a: Common = { id: 1 };
return a;
}
public static firstCaseFunction(): Common {
const ok: Common = this.lowestCommonDenominator();
return ok;
}
public static secondCaseFunction(): AdditionalInformation {
// Property 'myname' is missing in type 'Common' but required in type 'AdditionalInformation'.ts(2741)
const ko: AdditionalInformation = this.lowestCommonDenominator();
return ko;
}
}
But when I assign the function to an extended type, I get the error:
Property 'myname' is missing in type 'Common' but required in type
'AdditionalInformation'.ts(2741)
Is it possible to implement what I want?
This code snippet removes the error
export class Lib {
public static lowestCommonDenominator <T extends Common>(): T {
const a: Common = { id: 1 };
return a as T;
}
public static firstCaseFunction(): Common {
const ok: Common = this.lowestCommonDenominator();
return ok;
}
public static secondCaseFunction(): AdditionalInformation {
const ko: AdditionalInformation = this.lowestCommonDenominator<AdditionalInformation>();
return ko;
}
}
See this example code in Kotlin:
fun foo(bar: Int = 0, baz: Int) {
/* ... */
}
After decompiling it to Java code (Tools -> Kotlin -> Show Kotlin Bytecode -> Decompile) I got the following code
public static final void foo(int bar, int baz) {
}
// $FF: synthetic method
// $FF: bridge method
public static void foo$default(int var0, int var1, int var2, Object var3) {
if ((var2 & 1) != 0) {
var0 = 0;
}
foo(var0, var1);
}
I noticed that the resulting Java method has an unused Object var3 parameter.
I kind of thought that it may be related to functions in a class but when decompiling this code
class Foo {
fun foo(bar: Int = 0, baz: Int) {
/* ... */
}
}
I got this code
public final class Foo {
public final void foo(int bar, int baz) {
}
// $FF: synthetic method
// $FF: bridge method
public static void foo$default(Foo var0, int var1, int var2, int var3, Object var4) {
if ((var3 & 1) != 0) {
var1 = 0;
}
var0.foo(var1, var2);
}
}
As you can see the Object parameter is still unused and just sits there.
Upon additional tests I noticed the same behavior for extension methods. The same goes when the default parameter is last (i.e. fun foo(bar: Int, baz: Int = 0) {})
I've also done a basic test to check what is that value set to when calling that function using the code below
fun main(args: Array<String>) {
foo(baz = 2)
}
And
class Something {
init {
foo(baz = 2)
}
}
After decompiling it I got the following code
public static final void main(#NotNull String[] args) {
Intrinsics.checkParameterIsNotNull(args, "args");
foo$default(0, 2, 1, (Object)null);
}
And
public final class Something {
public Something() {
FooKt.foo$default(0, 2, 1, (Object)null);
}
}
Which makes even less sense whatsoever.
My question is: Why does Kotlin generate an unused parameter for functions with default parameters? Is it a bug?
According to this, currently it's unused, but is reserved for adding super calls with defaults later.
You can see it in action here:
open class Foo {
open fun foo(bar: Int = 0, baz: Int) {
/* ... */
}
}
class Blah: Foo() {
override fun foo(bar: Int, baz: Int) {
}
}
which will generate a bytecode-to-Java Foo of:
public class Foo {
public void foo(int bar, int baz) {
}
// $FF: synthetic method
// $FF: bridge method
public static void foo$default(Foo var0, int var1, int var2, int var3, Object var4) {
if(var4 != null) {
throw new UnsupportedOperationException("Super calls with default arguments not supported in this target, function: foo");
} else {
if((var3 & 1) != 0) {
var1 = 0;
}
var0.foo(var1, var2);
}
}
}
I'm looking for the equivalent of the following Obj-C code in Swift:
- newInstanceOf:(id)classRef {
return [classRef new];
}
and then to use it:
id instance = [whatever newInstanceOf:NSArray.class]
[instance isKindOfClass:NSArray.class] == YES
I have tried using a Swift template:
func newSomething<T>(classRef:T.Type) -> T {
return classRef()
}
I get the error: error: 'T' cannot be constructed because it has no accessible initializers
You could create a protocol to act as a type constraint for objects initializable by a void-argument initializer, and thereafter extend your types of choice to this protocol.
protocol SimplyInitializable {
init()
}
extension Int : SimplyInitializable { }
extension Double : SimplyInitializable { }
extension String : SimplyInitializable { }
struct MyStruct {
var myInt : Int
init() {
myInt = 0
}
}
extension MyStruct : SimplyInitializable { }
func newSomething<T: SimplyInitializable>(classRef: T.Type) -> T {
return classRef.init()
}
/* Examples */
var a = newSomething(Int)
var b = newSomething(Double)
var c = newSomething("".dynamicType)
var d = newSomething(MyStruct)
var e = newSomething(a.dynamicType)
print(a.dynamicType) // Int
print(b.dynamicType) // Double
print(c.dynamicType) // String
print(d.dynamicType) // MyStruct
print(e.dynamicType) // Int
Actually in Swift, not all classes are guaranteed to have an init() initializer. It can work with NSObject classes though because NSObject does have that requirement.
func newInstanceOf<T:NSObject>(aClass:T.Type) -> NSObject
{ return aClass.init() }
let string = newInstanceOf(NSString) // ""
let date = newInstanceOf(NSDate) // 2016-01-15 05:27:29 +0000