0

I am learning kotlin and I want to find out how to implement the following code from java to kotlin:

private Question[] questions = new Question[] {
    new Question(R.string.question_a, true)
    new Question(R.string.question_b, false)
};

public class Question {

  private int resultId;
  private boolean answerT;

  public Question(int resId, boolean theAnswer) {
    resultId = resId;
    answerT = theAnswer'
  }
}

kotlin:

class Question {
    private var resultId:Int  = 0
    private var answerT:Boolean = false

    fun Question(resId:Int, theAnswer:Boolean) {
        resultId = resId
        answerT = theAnswer
    }
}

....
private val questions:List<Question> {
    Question(R.string.question_a, true),
    Question(R.string.question_b, false)
}

I am not sure how to initialize in kotlin.

Zoe
  • 27,060
  • 21
  • 118
  • 148
George
  • 5,808
  • 15
  • 83
  • 160

3 Answers3

3

First of all, you're using Java-style constructors. Kotlin constructors are denoted by the constructor keyword, or by using primary constructors (parenthesis after the class name). fun ClassName is not how constructors are declared in Kotlin.

The reason I'm pointing this out is because you won't be able to initialize your class properly if you don't have the constructors right.

You have two options: First is using secondary constructors:

constructor(resId: Int, theAnswer: Boolean) {
    resultId = resId
    answerT = theAnswer
}

The second is using primary:

class Question(var resId: Int, var theAnswer: Boolean) { // these might be val instead; change these if you don't change the vars. you can also remove the brackets if you don't have a class body.
}

Using var or val in primary constructors also declares them for the class. If you don't use var or val, they're only available in the init block, or for variable initialization (until the initialization of the class is done, just like in constructors). You can compare using var or val to also adding this.someField = someField, where as without it's just used in the constructor.


Also note that secondary constructors are required to call the primary constructor if one exists. You'll also need primary constructors for some classes that require passing specific fields that you can't initialize directly, whether it is because it requires a specific instance to work, or it's a singleton implementation of an abstract class or an interface.


As for the list, it depends on how you want to do it. Your Java code uses arrays, and not lists. For lists though, you use listOf(items), and for arrays, you can use arrayOf. arrayOf() works exactly like listOf, except it returns Question[], and not a List<Question>. The correct initialization of a list (or array) is like this:

val questions = listOf(Question(R.string.question_a, true), ...)

listOf takes a vararg argument of items, so you can also create empty lists or arrays like that (Though for empty arrays, that's kinda pointless).

Types are automatically inferred too, so you don't need to explicitly type : List<Question>, or listOf<Question>(...). You need to explicitly declare them if you don't pass any arguments.

There's also the option to manually add it if you feel like that. You can for an instance initialize lists directly and call .add on those.

Zoe
  • 27,060
  • 21
  • 118
  • 148
  • :Hi, I wanted to ask you.If I want to do this from java: `int question = questions[some_index]`?How can I do it in kotlin?Something like : `var question:Int = questions[some_index]`, but it expects `Int` and i has `questions` and it doesn't work.Thanks! – George Nov 20 '18 at 10:53
  • @George the `questions` list is a List of questions. Lists, maps, and arrays in Kotlin have an `operator fun get`, which enables the indexing operator. The code you have there simply gets a Question. If you want the resultId, you have to do `questions[index].resultId`. If you want to convert the `List` into a `List`, you can use `questions.map { it.resultId }`. But if you're getting them individually, just calling the field is easy. Also, you can use the indexing operator on any class with an `operator fun get`. – Zoe Nov 20 '18 at 10:57
  • :Hmm.I am bit confused how to use the `operator fun`.Something like this? `operator fun question:Int = questions[some_index]`.Note, that the `.resultId` does not appear as an option. – George Nov 20 '18 at 11:03
  • @George you don't use it like that. A class declares it. You use it by calling `someClassInstanceWithAnOperatorFunGet[someArg]`. `list.get(index)` == `list[index]`. If the field is private, you can't access it. Fields in Kotlin automatically generate getters and setters, which means `private var` can't be accessed outside the class. Depending on what you want, you can either make it public (which gives access to a public getter and setter), or you can make it public and change the access of the setter. You can see this for more details on that: https://stackoverflow.com/a/46376746/6296561 – Zoe Nov 20 '18 at 11:09
  • Changing the access of getters and setters in primary constructors work differently compared to in i.e. a class body. Even though your class isn't a data class, the same principle applies. And the actual syntax used in the first example in the linked answer works universally. Add visibility modifiers in front of it and you can change access. For a private setter, you can just do `private set`. It can still be accessed, but not changed. – Zoe Nov 20 '18 at 11:10
  • 1
    :Thanks for the info!I will study.For the moment, I removed the private as you said and it works fine: `var question:Int = questions[some_index].resultId` – George Nov 20 '18 at 11:15
2

You can use the listOf method:

private val questions: List<Question> = listOf(
    Question(R.string.question_a, true),
    Question(R.string.question_b, false))
yole
  • 92,896
  • 20
  • 260
  • 197
Jesper
  • 202,709
  • 46
  • 318
  • 350
0

Why can't you go with enum class ?

enum class Question(val resultId:Int, val answerT:Boolean) {
    A(R.string.question_a, true),
    B(R.string.question_b, false)
}

or equivalent code for kotlin (I can think of),

class Question(val resultId:Int, val answerT:Boolean)
val questionList = listOf(Question(R.string.question_a,true), Question(R.string.question_b, false))
Suryavel TR
  • 3,576
  • 1
  • 22
  • 25