TLDR: The JetBrains Academy Basic Kotlin course is...
# getting-started
b
TLDR: The JetBrains Academy Basic Kotlin course is causing me to lose the will to live (I've done lots of courses and non have had this effect on me). Can someone please recommend an alternative one for Basic Kotlin? The below seems like a bit of a stretch. "In other words, the
=
sign does not copy the object itself, it only copies a reference to it.". This only seems the case for immutable objects. if I made the variable a var this is not the case. This seems very important. I'm getting very disillusioned with the JetBrains Academy course. It's very slow going but still manages to seem to oversimplify things. Can anyone recommend a good beginners course with lots of excursuses? So far my favourite one is https://www.udemy.com/course/100-days-of-code/ (bit its a Python course). It covers a lot and the docent is not too bogged down with the fiddly, not very useful stuff. I really appreciate the effort they put in but I want something that is a bit more fun. I don't mind paying a bit.
l
What do you mean by not the case if you mark it var? If I have
class MyClass(var x: Int)
and I write
Copy code
val foo = MyClass(10)
val bar = foo
foo.x = 15
println("bar.x is ${bar.x}")
I’d expect to get “bar.x = 15”
In C++, if I say
bar = foo
, it copies the contents of foo into bar. Kotlin does not. If you’re familiar with pointers, you can think of it more like
bar = &foo
where bar is actually a
MyClass*
e
the only things that aren't assigned by reference are value types. value types are also immutable, so there isn't really any practical difference.
b
Copy code
val msg1 = "Hi"
var msg2 = msg1
msg2 = "Ben"
println(msg1)
println(msg2)
Outputs Hi Ben So does not seem to of just copied the reference to it
I probably missed something
Been a long day
j
msg2 = "Ben"
has no effect on msg1. msg1 is still a reference to "Hi"
l
Strings are an object. You could think of a string literal as String(bytes), but with a nicer syntax.
e
msg2
is not a reference to `msg1`; it is first a reference to the object referred to by
msg1
(
"Hi"
) and then a reference to
"Ben"
.
b
Bear in mind I don't know Jave, C++ or C.
j
in Kotlin when I say
x=foo
then x is a reference to the same object as foo. if I mutate the object referenced by foo, then the object referenced by x will also be mutated. Note: writing
foo=somethingElse
is not a mutation of the object referenced by foo. You're simply making foo reference something new. to mutate the object referenced by foo you'll usually need to change a property of it ie
foo.bar =2
now in some languages when I say
x=foo
I actually make copy of foo so that if I write
x.bar=2
it will have no effect on foo. Kotlin is not such a language
b
OK, I totally get the
OK, I totally get the idea of = creating a reference to an object rather than creating a copy of it. But with
Copy code
val msg1 = "Hi"
var msg2 = msg1
msg2 = "Ben"
println(msg1)
println(msg2)
This is not happening.
So when I create a mutable object from an immutable one I get a copy, which makes sense. This makes total sense to me, the point I was making was the tutorial did not make this clear, and it seems important.
e
if you mean
.toList()
,
.toMutableList()
,
.toSet()
,
.toMutableSet()
,
.toMap()
,
.toMutableMap()
, yes they all create a copy
👃 1
j
I think you're mixing terminology here. A val can be mutable and a var can be immutable
And btw strings are always immutable
Var vs val determines if I can make the variable reference something else. Immutability is about if the object itself can be changed. Ie a mutableList can be changed by adding or removing from the list
e
yep.
String
is immutable, a reference to a string is mutable if it's a
var
(can be replaced by a reference to a different string). a
StringBuilder
is mutable, a reference to a string builder is immutable if it's a
val
(the builder can still be mutated)
also
List
being "immutable" just means you can't mutate it through this reference (without downcasts); it's possible that a different reference can mutate it. (I think it would be better called unmodifiable) e.g.
Copy code
val x: MutableList<Int> = mutableListOf(1, 2, 3)
val y: List<Int> = x
y == listOf(1, 2, 3)
y.add(4) // not allowed
x.add(5) // allowed
y == listOf(1, 2, 3, 5)
j
@ephemient or "read-only"
👍 1
@Ben Edwards if you want really beginner level courses, I had found this one interesting: https://typealias.com/start/kotlin-variables-expressions-types/ I only read the first chapter but I found it well explained. Not sure you'll find it better but it's another option.
That said, I don't know the course you're talking about. Maybe you just got confused by the terminology/concept used here, and find contradictions where there are none
b
@Joffrey thanks, will give it a go. The thing that really did my head in was it went into the 'copy by reference' and 'referential integrity' without even covering the basic syntax of creating objects. It seems to love diving into the details without explaining the basics. I want a practical course.
I think maybe I should just dive into one of the udemy Android courses as hopefully it should cover the basics but be less like pulling teeth :).
l
I’ve honestly never been certain about courses that start with Kotlin. It may just be how I learn, but I never really understood programming well until I started Java. Once I learned the concepts with Java, I was able to move those concepts to other languages, including Kotlin. As a professional dev, the syntactic sugar of Kotlin is great, but as a beginner, it was just confusing.
I spent a long time copying lazy delegation from past projects before I realized that it’s just a wrapper around getFoo() that takes in a trailing lambda. With Java, things were a lot more direct. It makes the code much more verbose, but also more easy to understand as a beginner. I always liked that Java is so structured I could look at GitHub on my phone and know exactly what file a method was defined in just by checking the class name and import list, even if this was my first time looking at the project.
v
@Ben Edwards your example
Copy code
val msg1 = "Hi"
var msg2 = msg1
msg2 = "Ben"
println(msg1)
println(msg2)
has nothing to do with the statement your quoted. I think you still didn't quite understand it. •
"Hi"
is an immutable instance of
String
with value
Hi
"Ben"
is an immutable instance of
String
with value
Ben
msg1
is an immutable variable that can point to an instance of
String
msg2
is a mutable variable that can point to an instance of
String
So after
Copy code
val msg1 = "Hi"
var msg2 = msg1
msg1
and
msg2
both point to the instance
"Hi"
And after
Copy code
msg2 = "Ben"
msg1
still points at the instance
"Hi"
but
msg2
now points at the instance
"Ben"
. You nowhere try to modify the properties of the instance either variable is pointing to, but you just modify what independent instances the variables are pointing at. So your example has nothing to do with the statement you quoted. If you have
Copy code
data class Foo(var bar: String)
val msg1 = Foo("Hi")
val msg2 = msg1
msg2.bar = "Ben"
println(msg1.bar)
println(msg2.bar)
then you see what the sentence is meaning, that
msg1
and
msg2
point to the same instance that you modified with the
msg2.bar = ...
line.
👍 1
e
for immutable types, it (mostly) doesn't matter how many instances there are: you can't change them so they might as well be the same
Copy code
val a = "Hi"
val b = "H" + "i"
a == b
a === b // … maybe, but it shouldn't matter
(in this case, the compiler will join the strings at compile time, and grab them from the JVM string pool at runtime, so they're the same instance, but no requirement that be the case afaik)
l
String pool behaviour will likely vary with Kotlin/Native and Kotlin/JS
v
Anyway, it absolutely irrelevant to the topic here and will just confuse the OP more as he didn't even understand the "pointers", so while of course correct, maybe not a too good idea to mention it here. 🙂
b
@Björn Kechel think I get it. While the 2 are the same they are both referencing the same thing but when I set msg2 to something else this is no longer the case.
j
👏
v
Still the wrong Björn K. you ping. And not quite.
msg1
and
msg2
are never the same. They are two separate things that can point to an instance. They can point to the same instance or they can point to different instances. And if they point to the same instance, then modifying the instance the one points to, of course also modifies the instance the other points to as they point to the same instance. But
msg1
and
msg2
, the variables - not the instances they point to -, are always separate things and modifying what one points to has no influence on what the other points to. Maybe you should start with a general course about object oriented programming paradigm to learn some basics.
j
@Vampire I think that's a bit harsh to say no here. When saying
msg1
and
msg2
are the same, I think he meant "when they are set to the same reference"
👍 1
v
That was a typo, should have been "not quite". And I'm not sure he meant that, because that is exactly what he didn't get right and why he didn't understand the statement from the course.
j
Ok fair enough