First off, I’m absolutely loving Kotlin - wanted a JVM language to try that wasn’t just a copy of an existing language (i.e. JRuby) and was actually understandable (cough Scala cough). My company uses IntelliJ, and since every time I try to create a new Java class I see the option to create a new Kotlin file/class, I figured I’d look into it; glad I did.
Second, not sure if this has been discussed here; tried searching, but my search-fu isn’t necessarily the best, so I’ll gladly take a link to previous threads about it.
Since Kotlin allows including multiple classes within a file, it seems like it’d be useful to include imports within a specific class at the very least; function-level scoping could arguably be useful as well, but might be a little overboard. I’m not suggesting this out of necessity on my part, but I can think of a simple use case where it might come in handy:
// SomeStuff.kt
class DataProcessor {
import kotlin.collections.List;
val data: List<Stuff> = listOf(blah);
}
class DataPresenter {
import java.awt.List;
val listView: List by listPresenterPropertyStuff()
}
Currently, there’s the “as” keyword approach (which I do like, btw):
// SomeOtherStuff.kt
import kotlin.collections.List;
import java.awt.List as AwtList;
class DataProcessor {
val data: List<Stuff> = listOf(blah);
}
class DataPresenter {
val listView: AwtList by listPresenterPropertyStuff()
}
Which is fine, but I can also see that method causing confusion and possible refactoring hiccups. There’s also the good ol’ fashioned fully-qualified class name, but we’re not savages. The other alternative would be putting everything into separate files; I’d imagine that if the code is big enough to where the “as” keyword leads to confusion and/or refactoring problems, it’s big enough to warrant putting into separate files. Of course, I’ve also worked on enough code to know that “breaking into multiple files” would be a task that will always get scheduled for tomorrow, right after improving code coverage of unit tests but before adding documentation.
Granted, we’ve been working around this kind of stuff in Java-land from day one, but if nothing else I imagine it might help keep generated code a little cleaner as well - no clue how the Kotlin compiler actually generates the Java code/classes behind the scenes, but it looks like it’d be easier to ensure that the generated DataProcessor class above would only import the kotlin.collections.List, while the DataPresenter class would only import the awt List.
I’m all for class-scoped imports; further scoping conditions like function- or block-level might get a little more convoluted or confusing, so I’d leave that up in the air for smarter folk to debate.
I can see the potential for ambiguity with scoping with this approach though:
// SomeOtherStuff.kt
import kotlin.collections.List;
class DataProcessor {
val data: List<Stuff> = listOf(blah);
}
class DataReader {
import java.util.List;
import com.initech.legacy.ListReader;
val input: List<InputStuff> = ListReader.readFromDatabase();
}
class DataPresenter {
import java.awt.List;
val listView: List by listPresenterPropertyStuff()
}
This might be a non-issue with smaller classes like these examples, but if the type use is removed from the class-scoped import by several lines, it might get confusing to the developer. I’d say at the very least it would warrant a compiler warning, maybe an error but that might be too strong; just something to indicate that the List they think they’re using might not be what they’re actually getting.
Thoughts? (And apologies for the long-winded post.)