Why is my kotlin hash set not adding elements - kotlin

I am new to kotlin and I want to make an abstract/open class or interface, something that can be implemented by other classes. Let's call it Test. Now Test needs to have a HashSet (the docs say it requires less memory than a normal set) that every derived class will implement and fill with its own values.
interface Test {
val players: HashSet<String>
}
class Supa: Test {
override val players = hashSetOf<String>()
fun later() {
players.add("new player")
}
}
fun main() {
Supa().later()
println(Supa().players)
}
The above will output []. It seems that for some reason players doesn't get updated. After playing around in the kotlin playground I found out that if I print players from inside later() it will show the added element. Maybe it creates a new instance of player that exists in the scope of the function?? Could someone please show me how I can make an abstract hashSet that the derived class can override and fill with values that stay in the set?

The problem here is that you create two separate instances of Supa. You invoke later() on one of them and then print players of another one. Each Supa() creates a new instance.
You need to store Supa instance inside a variable and use it in both places:
val supa = Supa()
supa.later()
println(supa.players)
This isn't really specific to Kotlin. Your code would work the same in other languages as well.

Related

can I create top level instance in kotlin?

If I have app.kt file in kotlin, can I create instance like appKt()? Thanks.
Kotlin has top level function. For example I can write in app.kt:
val a = 123
fun abc() {}
appKt.abc()
my question is if I can create appKt instance and call instance method
Only classes can be instanced.
Instead of loose function fun abc() {}, this should be the method of a class:
class appKt() {
// private var a: Integer = 123
fun abc() {}
}
No, you can't put arbitrary code at the top level.
You can put only definitions of classes (just as in Java), objects, functions, and properties.
It wouldn't make much sense to put loose code there, anyway: when would it run?
It's not clear what you're trying to achieve with this. If you want some code that gets run when your program starts up, then you could put it into a top-level function — but you'd then have to call that function (e.g. from your main() method). Or you could put it in the init block of the companion object to a class that you know will be loaded. Or if you're using a framework such as Android or Spring, then that will probably provide ways to specify code to be run at start-up.

How to mock Kotlin's List.forEach?

For the given code below, in Kotlin, it's not possible to execute the function forEach (or anything similar, map, filter, so on...) because BarList is mocked. So the native implementation of forEach and relatives are not being called. After a bit of search on the internet I came with this:
public class BarList<E> extends AbstractList<E> implements OrderedBarCollection<E> {
//...
}
//...
val mockedList: BarList<Foo> = mockBarList()
val fooList = listOf(Foo())
`when`(mockedList.iterator()).thenReturn(fooList.iterator())
`when`(mockedList.size).thenReturn(fooList.size)
com.nhaarman.mockito_kotlin
.doCallRealMethod()
.`when`(mockedList)
.forEach(Mockito.any<Consumer<Foo>>()) //Attempt to call the Consumer.
mockedList.forEach { foo ->
//Not executing
}
I tried this above based on the answer of this question: https://stackoverflow.com/a/49407513/2430555
I also tried:
com.nhaarman.mockito_kotlin.doCallRealMethod().`when`(mockedList).forEach(any())
But it's causing:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
0 matchers expected, 1 recorded:
//...
The definition of forEach in the Kotlin source code is:
public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit
I think I should replace any() with something that matches action: (T) -> Unit, but I am not sure how to do this.
I don't mind to use interactor if needed, but I need to at least make forEach run as expected. Could you guys please help me?
Regards,
Pedro
The solution is to use thenAnswer instead of thenReturn for the mocked list.
`when`(mockedList.iterator()).thenAnswer { fooList.iterator() }
Reason:
Author: Tobias Berger
an iterator is only good for going through the list once. Therefore
you usually get a new one every time you call the iterator() function.
If you mock that with thenReturn(messageList.iterator()) , it will
just call that once on messageList and reuse that iterator instance
every time you try to get one for your mock. Once your first loop over
this iterator is finished, it will always say it has no more items.
With thenAnswer you define a supplier that is called each time your
mocked function is used, providing a new iterator for each call (as
would be expected)
I think you cannot mock extension funcitons at all, while they are not members of target class.
forEach is Just outer helper for Iterable
In this case you will be still calling usual forEach of kotlin on fooList.
And i don't understand what is the motivation to mock collections especially substitute iterator of mocking OrderedBarCollection with simple ArrayList (listOf), what is requirement to do it?

Initialize new arraylist with (custom) items in one line in Kotlin

In Kotlin I created an extension function to initialise a new ArrayList with custom items, like this:
fun <T> arrayListFrom(vararg item: T): ArrayList<T> {
return item.toMutableList() as ArrayList<T>
}
In this way I can easily create an arraylist like this
arrayListFrom(MyCustomItem(1), MyCustomItem(2))
... without creating a new-empty one, and adding all elements to it one by one
Kotlin has so many useful functions for collections, I cannot imagine I need this extension for easy arrayList initialisation, but couldn't find another simple way. Am I missing out on some useful Kotlin function here?
arrayListOf(items)
So you can just do
arrayListOf(MyCustomItem(1), MyCustomItem(2))
One more easy way to initialize ArrayList not exactly one line.
object: ArrayList<instanceType>() {
init{
add(instance1)
add(instance2)
}
}
Another nifty trick is to leverage Kotlin's basic Array type. Its constructor has an optional init function which allows for cool and simple inits like so val newArray = Array(2) { MyCustomItem(i+1) } which would make [ MyCustomItem(1), MyCustomItem(2) ].
To get an arrayList out of it, just add toCollection(ArrayList()) to the end like so
val newArrayList = Array(2) { MyCustomItem(i+1) }.toCollection(ArrayList())
and presto! The array gets created, and the items get sent to a destination arrayList. You can use the arrayList as needed, and it was done in only one line!
Disclaimer: It's probably slower given the transfer involved under the hood, so use with care of course!

What is the benefit of having a private constructor and a use a method inside companion object to instantiate a class?

I've bumped into this code and I'm not sure why would anyone do this. Basically the author decided for making the class constructor private so that it cannot be instantiated outside the file, and added a public method to a companion object in the class that creates a new instance of this class. What is the benefit of this approach?
This is what I found:
class Foo private constructor(private val arg1: Any) {
//more code here..
companion object {
fun newFoo(arg1: Any) = Foo(arg1 = arg1)
}
}
Why is it better than this?
class Foo(private val arg1: Any) {
//more code here..
}
There are several benefits to providing a factory method instead of a public constructor, including:
It can do lots of processing before calling the construstor. (This can be important if the superclass constructor takes parameters that need to be calculated.)
It can return cached values instead of new instances where appropriate.
It can return a subclass. (This allows you to make the top class an interface, as noted in another answer.) The exact class can differ between calls, and can even be an anonymous type.
It can have a name (as noted in another answer). This is especially important if you need multiple methods taking the same parameters. (E.g. a Point object which could be constructed from rectangular or polar co-ordinates.) However, a factory method doesn't need a specific name; if you implement the invoke() method in the companion object, you can call it in exactly the same way as a constructor.
It makes it easier to change the implementation of the class without affecting its public interface.
It also has an important drawback:
It can't be used by subclass constructors.
Factory methods seem to be less used in Kotlin than Java, perhaps due to Kotlin's simpler syntax for primary constructors and properties. But they're still worth considering — especially as Kotlin companion objects can inherit.
For much deeper info, see this article, which looks at the recommendation in Effective Java and how it applies to Kotlin.
If you want to change Foo into an interface in the future the code based on the method will keep working, since you can return a concrete class which still implements Foo, unlike the constructor which no longer exists.
An example specific to android is, that Fragments should be constructed with an empty constructed, and any data you'd like to pass through to them should be put in a bundle.
We can create a static/companion function, which takes in the arguments we need for that fragment, and this method would construct the fragment using the empty constructor and pass in the data using a bundle.
There are many useful cases, for example what Kiskae described. Another good one would be to be able to "give your constructors names":
class Foo<S: Any, T: Any> private constructor(private val a: S, private val b: T) {
//more code here...
companion object {
fun <S: Any> createForPurposeX(a: S) = Foo(a = a, b = "Default value")
fun createForPurposeY() = Foo(a = 1, b = 2)
}
}
Call site:
Foo.createForPurposeX("Hey")
Foo.createForPurposeY()
Note: You should use generic types instead of Any.

Way to share data between classes in kotlin

I have 2 kotlin classes and both of them implement the interface myVariables. Inside myVariables is a variable named money. What I am trying to do is have the same variable(and keep its value too) be used inside both classes. Is this a good way to do it?
class MainActivity : myVariables, AppCompatActivity() {override val money = 0}
abstract class ShopActivity : myVariables, AppCompatActivity() {override val money = 0}
The interface:
interface myVariables {
val money: Int
}
What is a better way to use the same variable in both of my classes without redefining its value. For example if the variable has gained a value of 5 in the MainActivity class, I want to use the same variable with a value of 5 in the ShopActivity class.
I want the same effect as if this variable was global in the file that is using it, if that makes any sense.
You're looking for singleton. And the idiomatic way to create them in Kotlin is to create object (not class), which will hold your variables. Like this:
object MyVariables {
const val string = "foo"
val pops = 4
}
And then you can use it in your class like this:
class MyClass {
fun myMethod() {
println(MyVariables.string)
}
}
Of course you can use vars, not vals if you need to change them. But be warned that having a global mutable state is generally a bad idea because it's hard to track over the code, where variable is changed from.
Also note that generally it's a bad idea to start names of interfaces from lowercase because it breaks conventions and makes code less readable. It took a couple seconds for me to understand that myVariables isn't variable name.