In the following code snippet i have created 4 instances of CompanionClass and want to know how many
instances i have created , so have tried many ways but didn't work. Here i used companion object class
to keep track of objects but i know it has no connection with objects because keepTrackOfObjects() is
static. Can anyone help me solve this, please?
class CompanionClass
{
companion object{
var numberOfObjects = 0
fun keepTrackOfObjects() = println("number of created objects currently is: +
${++numberOfObjects}")
}
}
fun main()
{
val obj1 = CompanionClass()
CompanionClass.keepTrackOfObjects()
val obj2 = CompanionClass()`enter code here`
val obj3 = CompanionClass()
val obj4 = CompanionClass()
CompanionClass.keepTrackOfObjects()
}
// output is
// 1
// 2
You can use the init block to count the elements you created:
class CompanionClass {
companion object {
var counter: Int = 0
fun counter(): Int {
return counter
}
}
init {
counter++
}
}
You can test the behavior in this kotlin playground.
The problem is with your companion Object,
var numberOfObjects = 0
will initialise the variable every time you create a new instance. So create this variable in a separate class where keep all static content and use it from there. then you companion object will be like this.
companion object{
fun keepTrackOfObjects() = println("number of created objects currently is: +
${++numberOfObjects}")
}
To achieve this, you should increment your numberOfObject in a init statement.. Get a look at the code below
class User (var firstName:String,var lastName:String){
companion object {
var numberofinstance:Int = 0
fun getNumberOfInstance() = println("Nombre d'instance = $numberofinstance")
}
init {numberofinstance++}
}
Now you can use it in your main function
fun main(){
val user1=User("bob","marley")
val user2=User("bonkey","reynard")
val user3=User("jobbs","steve")
val user4=User("bill","naim")
val user5=User("jeff","romain")
User.getNumberOfInstance()
}
Output : Number of instance = 5
Related
After implementing viewmodels to jetpack compose app when I running the app it's showing a error :-
Attempt to invoke interface method 'boolean java.util.Set.contains(java.lang.Object)' on a null object reference
java.lang.NullPointerException: Attempt to invoke interface method 'boolean java.util.Set.contains(java.lang.Object)' on a null object reference
at com.example.android.ui.GameViewModel.pickRandomWordAndShuffle(GameViewModel.kt:21)
at com.example.android.ui.GameViewModel.(GameViewModel.kt:10)
here is my code:-
import androidx.lifecycle.ViewModel
import com.example.android.unscramble.data.allWords
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
class GameViewModel : ViewModel() {
private val _uiState =
MutableStateFlow(GameUiState(currentScrambledWord = pickRandomWordAndShuffle()))
val uiState: StateFlow<GameUiState> = _uiState.asStateFlow()
private var _count = 0
val count: Int
get() = _count
private lateinit var currentWord: String
private var usedWords: MutableSet<String> = mutableSetOf()
private fun shuffleCurrentWord(word: String): String {
val tempWord = word.toCharArray()
// Scramble the word
tempWord.shuffle()
while (String(tempWord) == word) {
tempWord.shuffle()
}
return String(tempWord)
}
private fun pickRandomWordAndShuffle(): String {
// Continue picking up a new random word until you get one that hasn't been used before
currentWord = allWords.random()
if (usedWords.contains(currentWord)) {
return pickRandomWordAndShuffle()
} else {
usedWords.add(currentWord)
return shuffleCurrentWord(currentWord)
}
}
private fun resetGame() {
usedWords.clear()
_uiState.value = GameUiState(currentScrambledWord = pickRandomWordAndShuffle())
}
init {
resetGame()
}
}
It's not showing any compile time errors. I don't konw what should I do.
You're initializing _uiState before you initialize usedWords. This calls pickRandomWordAndShuffle() before usedWords has been initialized, so it's still null in the GameViewModel instance being created.
If you move the declaration of usedWords above _uiState it should work.
HOWEVER: It's generally a bad idea to call member functions before an instance has been fully initialized, for this exact reason.
You could make _uiState and uiState lazy, which would make this safer. For example:
// Copyright 2023 Google LLC.
// SPDX-License-Identifier: Apache-2.0
private val _uiState by lazy {
MutableStateFlow(GameUiState(currentScrambledWord = pickRandomWordAndShuffle()))
}
val uiState: StateFlow<GameUiState> by lazy { _uiState.asStateFlow() }
which will wait until something uses uiState (which looking at your code only happens externally, so you'll be guaranteed that it won't be initialized until the GameViewModel has been fully initialized.
I try to put a key-value to ConcurrentHashMap in Kotlin buf failed. The compiler tells me: No set method providing array access.
class MysqlDataProviderProxy() {
private val NULL: Any = Object()
var unionMaps: Map<Long, Any> = ConcurrentHashMap()
fun init() {
unionMaps[1] = NULL // No set method providing array access
}
}
I don't know what does it mean. Is ConcurrentHashMap in Kotlin unmutable?
As Sweeper says you have the wrong type on unionMap.
Is ConcurrentHashMap in Kotlin unmutable
No, but unlike Java Maps/Lists/Sets have mutable and immutable interfaces and the interfaces Map, List, Set are the immutable variation.
You want this:
class MysqlDataProviderProxy() {
private val NULL: Any = Object()
var unionMaps: MutableMap<Long, Any> = ConcurrentHashMap()
init {
unionMaps[1] = NULL
}
}
And the other thing is that your original function init() does not get executed as the instance is constructed, you probably want init {... as I show above
but the problem with that approach is that now you have made the map mutable outside your proxy class which might not be your intention, in which case you could do this:
class MysqlDataProviderProxy() {
private val NULL: Any = Object()
var unionMaps: Map<Long, Any> = ConcurrentHashMap()
init {
(unionMaps as MutableMap)[1] = NULL
}
}
I'm actually new at Kotlin, and I encounter the following problematic:
I have a class holding an ArrayList of EnsembleVerifier class.
This other class is instantiated with an ArrayList of Square.
When I tried to get this ArrayList, I discovered that this one has no element inside.
Is there any absurdity/misconception in my code? Is it something else? Thank you in advance! :)
GridVerifiers.kt
class GridVerifiers(private val grid: Grid) {
private var verifiers: ArrayList<EnsembleVerifier> = ArrayList()
init {
generateVerifiers()
}
private fun generateVerifiers() {
generateLineVerifiers()
generateColumnVerifiers()
generateSubGridVerifiers()
}
private fun generateLineVerifiers() {
val line: ArrayList<Square> = ArrayList()
for (lineIndex in grid.gridState.indices) {
for (columnIndex in grid.gridState.indices)
line.add(grid.gridState[lineIndex][columnIndex])
println(line.size) // returns 9
verifiers.add(EnsembleVerifier(line))
line.clear()
}
}
...
EnsembleVerifier.kt
class EnsembleVerifier(private val squares: ArrayList<Square>) {
...
fun isValid(): Boolean {
val buffer: ArrayList<Int> = ArrayList()
println(squares.size) // returns 0!
for (square in squares) {
if (square.value in buffer) return false
buffer.add(square.value)
}
return true
}
In java most of the time you are working with references to objects. This means in your case, that your are always working with the same array line. Therefore, when you call line.clear you are cleaning the array that that reference is pointing at, and that's causing your issue with empty arrays.
You need to generate new objects every time instead of cleaning the list.
private fun generateLineVerifiers() {
for (lineIndex in grid.gridState.indices) {
val line: ArrayList<Square> = ArrayList()
for (columnIndex in grid.gridState.indices)
line.add(grid.gridState[lineIndex][columnIndex])
println(line.size) // returns 9
verifiers.add(EnsembleVerifier(line))
}
}
I want to return multiple values from a function. As suggested by another SO answer, I used Destructuring with public class, but the problem is I can't assign the returned destructured result to already existing variables.
data class Result(val res1 :Int, val res2: Int)
class test{
fun retresult():Result{
return Result(2,2)
}
}
fun main(args: Array<String>) {
var var1:Int = 0
var var2:Int = 0
var des = test()
//(var1, var2) = des.retresult() this doesn't work
var1 = des.retresult().res1
var2 = des.retresult().res2 // **works but calls function twice**
}
I don't want to initialize local vals at return point like
val (var1, var2) = des.retresult()
You can assign these two variables without calling the function twice, using with:
fun main(args: Array<String>) {
var var1:Int = 0
var var2:Int = 0
var des = test()
with (des.retresult()) {
var1 = res1
var2 = res2
}
}
Alternatively, your function could take function arguments for setting the results, and then you can pass the setters for these properties. This wouldn't work for local variables, only member properties. If you use C, this is kind of like passing a pointer to a function so it can directly modify a variable rather than returning something.
class Test (var one: Int, var two: Int)
fun doSomething(result1: (Int) -> Unit, result2: (Int) -> Unit) {
result1(2)
result2(2)
}
fun main() {
val test = Test(1, 1)
doSomething(test::one::set, test::two::set)
}
There's an open (and mostly forgotten, it seems) feature request for what you suggested, destructuring assignment to existing variables.
Is it possible to initialize an companion object before the init block in a Kotlin class? If so, how? If not, is there a way to accomplish the same thing.
I have the following scenario,
class A(val iname: String) {
init {
foo.add(this)
}
companion object B {
#JvmField val STATIC = A("hi")
#JvmField val foo = mutableListOf<A>()
}
fun printAllStatics() {
for (a in foo) {
print(a.iname)
}
}
}
and calling printAllStatics causes a null-pointer exception.
The property initializers and init blocks are executed in exactly the same order in which they are placed in a class/object body. Here's an example:
companion object B {
init {
print("1 ")
}
#JvmField val foo = mutableListOf<A>().apply { print("2 ") }
#JvmField val bar = mutableListOf<A>().apply { print("3 ") }
init {
print("4")
}
}
It will print 1 2 3 4.
So, in your case, swapping the two declarations in the companion object is enough:
companion object B {
#JvmField val foo = mutableListOf<A>()
#JvmField val STATIC = A("hi")
}
Just change the order of lines:
#JvmField val foo = mutableListOf<A>()
#JvmField val STATIC = A("hi")
Before you used foo in A but it wasn't initialized.