Python vars() in Kotlin - kotlin

This python code
class Test:
def __init__(self):
self.one = "python"
self.two = "is"
self.three = "fun!"
t=Test()
print(vars(t))
prints a collection of fields and their values:
{'one': 'python', 'two': 'is', 'three': 'fun!'}
How can I do the same in Kotlin?

If you are using the Koltin data class you can just print the class
class Test(val one: String, val two: String, val three: String)
fun main(args: Array<String>) {
val test = Test("Kotlin", "is", "fun")
println(test)
}
which will produce: Test(one=Kotlin, two=is, three=fun)
Kotlin data classes also provide a componentN() function. Look here for some informations about data classes in Kotlin
For regular classes you can try the approach of this answer

Related

Kotlin Generic problem, UNCHECKED_CAST , required:Nothing

#file:Suppress("UNCHECKED_CAST")
data class Element<T>(
val key: String,
val valueOne: T,
val valueTwo: T,
val comparator: Comparator<T>,
val comparatorValue: CompareResult
)
enum class CompareResult(
val value: Int
) {
LESS(-1),
EQUAL(0),
GREATER_THAN(1)
}
fun <T> matchesComparison(list:Collection<Element<T>>): Pair<Boolean, List<String>> {
val failedComparisons = mutableListOf<String>()
for (element in list) {
val compareValue = element.comparator.compare(element.valueOne, element.valueTwo)
if (element.comparatorValue.value != compareValue) {
failedComparisons.add(element.key)
}
}
return Pair(failedComparisons.isEmpty(), failedComparisons)
}
val stringComparator = Comparator.comparing(String::toString)
val intComparator = Comparator.comparing(Int::toInt)
val elementsToCompare = listOf(
Element("number", 1, 2, intComparator, CompareResult.LESS),
Element("first name", "a", "a", stringComparator, CompareResult.EQUAL),
Element("last name", "a", "b", stringComparator, CompareResult.EQUAL)
)
matchesComparison(elementsToCompare).second.joinToString(", ","Failed elements: \"","\"")
I often get faced with comparing two different object properties with the same values.
As an example object A has props number,firstname,lastname. What i want to do is create a list have and have a function which goes over these Elements and returns which props have failed the comparison. I've managed to use generics for both the object and the matchesComparison function which returns the failed comparisons. The problem begins when i want to pass this list which is of type Collection<Element<out Any>> to this function is i get a type missmatch. instead of using unchecked casts to force the Comparator to be of type Any i would like to do this
val stringComparator = Comparator.comparing(String::toString)
val intComparator = Comparator.comparing(Int::toInt)
The result value that of the script above should be Failed elements: "last name"
I tried changing the signature of the function to out any but then the comparator.compare method has both params as of type Nothing. I really want to avoid unsing unchecked casts.
matchesComparison() doesn't need to be generic in this case. It doesn't really care what is the type of the whole input collection, so we can simply use * here.
Then we have another problem. The compiler isn't smart enough to notice that while we perform operations on a single element, all its properties are of matching types. As a result, it doesn't allow to use element.comparator on element.valueOne and element.valueTwo. To fix this problem, we simply need to create a separate function which works on a single Element, so it understand the type for all properties is the same:
fun matchesComparison(list:Collection<Element<*>>): Pair<Boolean, List<String>> {
fun <T> Element<T>.matches() = comparatorValue.value == comparator.compare(valueOne, valueTwo)
val failedComparisons = mutableListOf<String>()
for (element in list) {
if (!element.matches()) {
failedComparisons.add(element.key)
}
}
return Pair(failedComparisons.isEmpty(), failedComparisons)
}
Also, I believe such matches() function should be actually a member function of Element. It seems strange that while Element is pretty independent and it contains everything that is needed to perform a comparison, it still requires to use external code for this. If it would have a matches() function then we wouldn't need to care about its T. matches() would work with any Element.

Why is subtyping preserved in this example without using the out keyword?

Here a have a generic type, but I don't understand why even though I didn't made the type T covariant, I can add subclasses of Player to my generics class and function which has an upper bound T: Player; so why is the subtyping preserved without using the out keyword; and because of this I can - wrongly- add a BaseballPlayer and GamesPlayer to a football team. 1
class Team<T : Player>(val name: String, private val players: MutableList<T>) {
fun addPlayers(player: T) {
if (players.contains(player)) {
println("Player: ${(player as Player).name} is already in the team.")
} else {
players.add(player)
println("Player: {(player as Player).name} was added to the team.")
}
}
}
open class Player(open val name: String)
data class FootballPlayer(override val name: String) : Player(name)
data class BaseballPlayer(override val name: String) : Player(name)
data class GamesPlayer(override val name: String) : Player(name)
val footballTeam = Team<Player>(
"Football Team",
mutableListOf(FootballPlayer("Player 1"), FootballPlayer("Player 2"))
)
val baseballPlayer = BaseballPlayer("Baseball Player")
val footballPlayer = FootballPlayer("Football Player")
val gamesPlayer = GamesPlayer("Games Player")
footballTeam.addPlayers(baseballPlayer)
footballTeam.addPlayers(footballPlayer)
footballTeam.addPlayers(gamesPlayer)
The mutable list you defined on this line:
mutableListOf(FootballPlayer("Player 1"), FootballPlayer("Player 2"))
is not a MutableList<FootballPlayer>. It is a MutableList<Player>, since you didn't specify its type, so the compiler used type inference to assume you want a MutableList<Player> to fit the constructor argument for your Team<Player> constructor.
So, it is valid to put any kind of Player into a MutableList<Player>, since it can only ever return items of type Player. It's still type safe.
If you had been explicit about the type, it would have been a compile error:
val footballTeam = Team<Player>(
"Football Team",
mutableListOf<FootballPlayer>(FootballPlayer("Player 1"), FootballPlayer("Player 2"))
//error, expected MutableList<Player>
)
Or if you had omitted the type from the Team constructor, it would have assumed you wanted a Team<FootballPlayer> and you would have had an error when trying to add other types of player:
val footballTeam = Team(
"Football Team",
mutableListOf(FootballPlayer("Player 1"), FootballPlayer("Player 2"))
)
// ^^ is a Team<FootballPlayer> because of type inferrence.
footballTeam.addPlayers(BaseballPlayer("Foo")) // error, expected FootballPlayer

How to get String description/value?

In Kotlin, how to get the raw value of the String?
For example,
val value: String = "Adrian"
Expected result:
"Cannot find value: Adrian"
I am coming from Swift and I know in swift it works like this
let value: String = "Adrian"
print("Cannot find \(string.description): \(value)")
Another example in Swift,
let a: String = "b"
print("\(a.description) = \(a)"
///prints "a = b"
Im guessing a String extension is needed given I read the Kotlin String documentation and seems none of the choices provides the expected result.
A simple problem but I really can't solve it:(
This might help you. For this you have to use Kotlin reflection:
Example:
data class Person(val name:String)
fun main(){
val person = Person("Birju")
val prop = person::name
println("Property Name: ${prop.name}")
println("Property Value: ${prop.get()}")
}
How about
println("value :$value")
You don't need concatination operator(+) to concat strings in kotlin

Does scalamock support mocking curried mehtod that has implicit and repeated parameters?

I need to mock following method using scalamock, but I didn't manage to do it. It is curried, has implicit and repeated parameters in the same time.
Does scalamock library support mocking such combination?
def apply(key: String, args: Any*)(implicit lang: Lang): String
How about this?
"complicated paramter lists" should "be mockable" in {
trait Foo {
def apply(key: String, args: Any*)(implicit lang: String): String
}
val m = mock[Foo]
(m.apply(_: String, _: Seq[Any])(_: String)) expects(*, *, *) returning "Foo" once()
implicit val s = "foo"
m.apply("bar", 5, true, 42.0) should be ("Foo")
}

What is the smartest way to copy a Map in Kotlin?

I'd like to get a new instance of some Map with the same content but Map doesn't have a built-in copy method. I can do something like this:
val newInst = someMap.map { it.toPair() }.toMap()
But it looks rather ugly. Is there any more smarter way to do this?
Just use the HashMap constructor:
val original = hashMapOf(1 to "x")
val copy = HashMap(original)
Update for Kotlin 1.1:
Since Kotlin 1.1, the extension functions Map.toMap and Map.toMutableMap create copies.
Use putAll method:
val map = mapOf("1" to 1, "2" to 2)
val copy = hashMapOf<String, Int>()
copy.putAll(map)
Or:
val map = mapOf("1" to 1, "2" to 2)
val copy = map + mapOf<String, Int>() // preset
Your way also looks idiomatic to me.
The proposed way of doing this is:
map.toList().toMap()
However, the java's method is 2 to 3 times faster:
(map as LinkedHashMap).clone()
Anyway, if it bothers you that there is no unified way of cloning Kotlin's collections (and there is in Java!), vote here: https://youtrack.jetbrains.com/issue/KT-11221
Add this extension (to convert entries to pairs)
val <K, V> Map<K, V>.pairs: Array<Pair<K, V>>
get() = entries.map { it.toPair() }.toTypedArray()
And then you can easy combine immutable maps using default Kotlin syntax.
val map1 = mapOf("first" to 1)
val map2 = mapOf("second" to 2)
val map3 = mapOf(
*map1.pairs,
"third" to 3,
*map2.pairs,
)