Will `var allByDefault: Int ?` cause error? - kotlin

In the section: Properties and Fields of the reference of kotlin, the following examples is written:
var allByDefault: Int? // error: explicit initializer required, default getter and setter implied
However, I test the code and there is no error in compiling and running.
Here is my code"
fun main(args:Array<String>){
var allByDefault:Int?
}
So why does the documentation write:
error: explicit initializer required, default getter and setter implied
I have searched google for help but haven't found any result which can help me.
#toniedzwiedz 's answer has solved the issue. It's my fault. I mistook property and variable.

fun main(args:Array<String>){
var allByDefault:Int?
}
What you have here is a var local to the main method, not a property.
class MyClass {
//this is a property of MyClass that requires some means of initialization
var allByDefault: Int? // Error: Property must be initialized or be abstract
fun foo() {
var local: Int? // this is a local variable defined in the scope of foo, which is fine
// ...
}
}

Related

Default value for generic member

I'm trying this:
class Foo<T> {
var member: T = T()
}
...but the Kotlin compiler gives me an error: Type parameter T cannot be called as function.
How do I default-construct a generic member variable?
Well, to access the type information, we need to use the reified keyword on the type, but this is only applicable in inlined functions. So instead of relying on direct construction, a workaround can be to use a generator function wrapped in the companion object that immediately sets the member right after construction
// Test class to verify the implementation
class Yolo {
override fun toString() = "Yolo swag"
}
class Foo<T : Any> {
lateinit var member: T
companion object {
inline fun <reified T : Any> newInstance() =
T::class.java.newInstance().let { memberInstance ->
Foo<T>().apply { member = memberInstance}
}
}
}
fun main() {
// generate a Foo<Yolo>
val foo = Foo.newInstance<Yolo>()
println(foo.member) // displays "Yolo swag"
}
It's implied that T has a public no-arg constructor, but in general case it may not be true. This code uses reflection to bypass compiler complains about it (which may end up with runtime error if you dissapoint the JVM expectations and indeed pass T without public no-arg constructor).
//Reified generics at class level are not yet supported in Kotlin (KT-33213),
// so you have to pass instance of `KClass` manually as a consructor parameter
class Foo<T : Any>(clazz: KClass<T>) {
var member: T = clazz.createInstance()
}

Check if a local lateinit variable is initialized

Member lateinit variables initialization can be checked with:
class MyClass {
lateinit var foo: Any
...
fun doSomething() {
if (::foo.isInitialized) {
// Use foo
}
}
}
However this syntax doesn't work for local lateinit variables. Lint reports the error: "References to variables aren't supported yet". There should logically be a way to do that since lateinit variables are null internally when uninitialized.
Is there a way to check if local variables are initialized?
The code you show in your question is actually fine in Kotlin 1.2 and beyond, since foo is an instance variable, not a local variable.
The error message you report and mentioned in Alexey's comment (Unsupported [References to variables aren't supported yet]) can be triggered by a true local variable, for example in the doSomethingElse method below.
class MyClass {
lateinit var foo: Any
fun doSomething() {
if (::foo.isInitialized) { // this is fine to use in Kotlin 1.2+
// Use foo
}
}
fun doSomethingElse() {
lateinit var bar: Any
if (::bar.isInitialized) { // this is currently unsupported (see link in Alexey's comment.
// Use bar
}
}
}
So it seems like this is currently unsupported. The only place that comes to mind where a lateinit local would be used would be if the local is variable captured in a lambda?

POJO class mismatch

I have the following class User that extends the BaseResponse class. I
am getting a type mismatch error:
Required => String
Found => String.Companion
for return apiKey
package com.touchsides.rxjavanetworking.network.model
import com.google.gson.annotations.SerializedName
class User: BaseResponse()
{
#SerializedName("api_key")
val apiKey = String
fun getApiKey(): String
{
return apiKey
}
}
abstract class BaseResponse(var error: String?=null)
{
}
How is the current implementation of this wrong
You used = instead : while declaration of api_key (apiKey = String). Which actually means you are initialising api_key with String.Companion Object.
And you don't need to create getApiKey() (getter) method as by default you will have getter method for your properties.
class User : BaseResponse() {
#SerializedName("api_key")
var apiKey: String? = null
private set
}
abstract class BaseResponse(var error: String? = null)
in fact you can use data class for this purposes
data class User(#SerializedName("api_key") val apiKey: String):BaseResponse()
fun main(args: Array<String>) {
Gson().fromJson<User>("{\"api_key\":\"my api key\"}", User::class.java).let {
println(it.apiKey)
}
}
A complete answer is that your code should look like this:
class User: BaseResponse()
{
#SerializedName("api_key")
lateinit var apiKey: String // must be set by something before being read
}
abstract class BaseResponse(var error: String?=null) {
}
You do not need a default value for the apiKey property if you intend to set it via deserialization later, if not then you should also add a default value as below. The getApiKey() method is removed because you do not need that in Kotlin, all properties have automatically generated getters built-in and by adding your own you would end up with a conflict between the generated getter and the one you manually created (two methods with the same name, same signature).
If you do need a default value for apiKey then stay with a var so that deserialization can work (if you intend to do that) and add a default empty string or make it a nullable string and set it to null.
class User: BaseResponse()
{
#SerializedName("api_key")
var apiKey: String = "" // if you want a default regardless, or make it nullable and null
}
abstract class BaseResponse(var error: String?=null) {}
You're stuck with the way Java do things. In kotlin when defining Getter and Setter, you don't have to write them yourself. Once you declare a variable, both methods would be automatically created.
EDIT: So delete the getter in your POJO class.

Kotlin, how to assign callback implementation to a variable

I'm trying to assign a callback implementation of an interface (defined inside a class A) to a variabile defined inside another class B. Let's say that class A has the interface OnSomethingHappens which defines a doSomething method.
Inside class B I've defined my callback variable like this:
private lateinit var callback:A.OnSomethingHappens
I need to create an instance of class A passing callback variabile to the constructor in this way:
myinstanceA = A(callback)
I'm trying to assign an instance of an anonymous class that implements A.OnSomethingHappens using this code:
callback = object : A.OnSomethingHappens {
override fun doSomething(..){
//here I put the implementation of this method
}
}
but the compiler says "expecting member declaration" for my callback variable and "name expected" for object.
What I'm doing wrong?
Instead, I'm able to define and at the same time assign the callback variable in this way:
private var callback = object : A.OnSomethingHappens {
override fun doSomething(..){
//here I put the implementation of this method
}
}
Why? Which are the differences and a possible solution?
I'm trying to assign an instance of an anonymous class that implements A.OnSomethingHappens using this code: ...
This should work, but only inside a method:
class B {
private lateinit var callback:A.OnSomethingHappens
fun someMethod() {
callback = object : A.OnSomethingHappens { ... }
}
...
}
Given the error message and that private var compiles (which doesn't inside a method), you are trying to set it directly in the body of the class instead:
class B {
private lateinit var callback:A.OnSomethingHappens
callback = object : A.OnSomethingHappens { ... }
...
}
This is illegal: the only code you can write there is member definitions and init blocks.
Also, if you can initialize callback directly where it's defined or inside init, there's no point to lateinit in the first place.
It's not obvious from the code snippets cut down to such small pieces, but your issue is that you're writing down the assignment inside the body of a class, but not inside a function.
Here's an example of a valid declaration and immediate assignment:
class A {
var x: X? = X()
}
Here's an example of an invalid assignment, which places an arbitrary expression in the body of a class:
class A {
lateinit var x: X
x = X() // expression placed inside the class body, invalid syntax
someFunction() // extra example, calling functions here is invalid in the same way
}
Instead, you could put this initialization inside a function:
class A {
lateinit var x: X
fun initializeX() {
x = X()
}
}
Or inside an initializer block (in this case, you don't even need lateinit):
class A {
var x: X
init {
x = X()
}
}
While I couldn't explain how to solve your exact problem, because I can't quite understand what code is in which class, I hope these examples and explanation helped.
Hmm, let me propose a variant. It's more simple for me:
import android.util.Log
class SomeClass {
fun mainMethod() {
ClassWithCallback(
{ myBackValue: String ->
logMyString(myBackValue)
}
)
//simplify
ClassWithCallback({ logMyString(it) })
}
private fun logMyString(myBackValue: String) {
Log.d("SomeClass", myBackValue)
}
}
class ClassWithCallback(private val myCallBack: (myBackValue: String) -> Unit) {
init {
// we do something here and back it by callback
val myString = "Hello! Pass me back!"
myCallBack.invoke(myString.toUpperCase())
}
}
Using Kotlin lambdas. Hope this will help you.

typescript interface initialization

My level of typescript is 'ABSOLUTE BEGINNER' but I have a good OOP background. I am building an with typescript that reference an external t.ds library that contains the following interface:
interface ISimpleObject {
foo: string;
bar?: any;
}
Now, if I want to call a method that has an IRequestConfig parameter, how do I create one? I can see different options:
Create a simple implementation of ISimpleObject. I don't like this approach because it looks like boilerplate code to me
don't initialize the object (I fear this could break something...):
var x :IsimpleObject;
x.bar = 'xxx';
callMethod(x);
Cast a pojo:
var x :IsimpleObject = <IsimpleObject>{foo: 'yyy', bar:'xxx'};
I don't like this approach either because it doesn't enforce type safety...
I guess this is a fairly trivial question and I am missing something trivial about typescript.
Typescript2:
const simpleObject = {} as ISimpleObject;
If you have an interface like:
interface ISimpleObject {
foo: string;
bar?: any;
}
This interface is only used at compile time and for code-hinting/intellisense. Interfaces are used to provide a rigorous and type-safe way of using an object with a defined signature in a consistent manner.
If you have a function using the interface defined above:
function start(config: ISimpleObject):void {
}
The TypeScript compile will fail if an object does not have the exact signature of the ISimpleObject interface.
There are multiple valid techniques for calling the function start:
// matches the interface as there is a foo property
start({foo: 'hello'});
// Type assertion -- intellisense will "know" that this is an ISimpleObject
// but it's not necessary as shown above to assert the type
var x = <ISimpleObject> { foo: 'hello' };
start(x);
// the type was inferred by declaration of variable type
var x : ISimpleObject = { foo: 'hello' };
start(x);
// the signature matches ... intellisense won't treat the variable x
// as anything but an object with a property of foo.
var x = { foo: 'hello' };
start(x);
// and a class option:
class Simple implements ISimpleObject {
constructor (public foo: string, public bar?: any) {
// automatically creates properties for foo and bar
}
}
start(new Simple("hello"));
Any time the signature doesn't match, the compile will fail:
// compile fail
var bad = { foobar: 'bad' };
start( bad );
// compile fail
var bad: ISimpleObject = { foobar: 'bad' };
// and so on.
There is no "right" way to do it. It's a matter of style choice. If it were an object that was constructed (rather than just directly passed as a parameter), I'd normally declare the type:
var config: ISimpleObject = { foo: 'hello' };
That way code-completion/IntelliSense will work anywhere I used the config variable:
config.bar = { extra: '2014' };
There is no "casting" in TypeScript. It is called a type assertion and shouldn't be needed in the cases described here (I included an example above where it could be used). There's no need to declare the variable Type and then use an assertion in this case (as the type was already known).
You can't create an instance of an interface since Typescript doesn't "translate" it into js. You can check the js that is created and you will see nothing in it. It's simple for compile errors, type safety and intelisense.
interface IStackOverFlow
{
prop1 : string;
prop2 : number;
}
public MyFunc(obj : IStackOverFlow)
{
// do stuff
}
var obj = {prop1: 'str', prop2: 3};
MyFunc(obj); // ok
var obj2 = {prop1: 'str'};
MyFunc(obj); // error, you are missing prop2
// getObj returns a "any" type but you can cast it to IStackOverFlow.
// This is just an example.
var obj = <IStackOverFlow> getObj();