Should we avoid naming a function same as an existing class in Kotlin? Why? - kotlin

Kotlin allows to name a function same as an existing class, e.g. HashSet with initializer function could be implemented like this:
fun <T> HashSet(n : Int, fn: (Int) -> T) = HashSet<T>(n).apply {
repeat(n) {
add(fn(it))
}
}
When used, it looks like a normal HashSet constructor:
var real = HashSet<String>()
var fake = HashSet(5) { "Element $it" }
Should this be avoided or encouraged and why?

UPD
In the updated coding conventions, there's a section on this topic:
Factory functions
If you declare a factory function for a class, avoid giving it the same name as the class itself. Prefer using a distinct name making it clear why the behavior of the factory function is special. Only if there is really no special semantics, you can use the same name as the class.
Example:
class Point(val x: Double, val y: Double) {
companion object {
fun fromPolar(angle: Double, radius: Double) = Point(...)
}
}
The motivation I described below, though, seems to still hold.
As said in documentation about the naming style:
If in doubt default to the Java Coding Conventions such as:
methods and properties start with lower case
One strong reason to avoid naming a function same to a class is that it might confuse a developer who will use it later, because, contrary to their expectations:
the function won't be available for super constructor call (if the class is open)
it won't be visible as a constructor through reflection
it won't be usable as a constructor in Java code (new HashSet(n, it -> "Element " + it) is an error)
if you want to change the implementation later and return some subclass instance instead, it will get even more confusing that HashSet(n) { "Element $it" } will construct not a HashSet but, for example, a LinkedHashSet
It's better to show it explicitly that it's a factory function, not a constructor, to avoid this confusion.
Naming a function same to a class is generally avoided in stdlib, too. Given SomeClass, in stdlib a preferred naming style for factory functions is someClassOf, someClassBy or whatever explains the semantics of the function best. The examples:
generateSequence { ... } and sequenceOf(...)
lazy { ... } and lazyOf(...)
compareBy { ... }
listOf(...), setOf(...), mapOf(...)
So, one should definitely have strong reason to have a function mimic a constructor.
Instead, a function's name might tell a user more (even everything) about its usage.

I agree with +hotkey. It's probably best to avoid confusion in this case.
If it's only used internally and all the other devs (if any) are okay with it, though, I'd say to go for it. Python acknowledges that idea and I love it. Heck, they go both ways, being okay with you naming a class in function case, too, if it feels more like it's acting like a function. But, Python doesn't have to deal with Java interop, so definitely don't do it for public code.

Related

T except one class

Suppose I've a class called Devil
class Devil
and I've method called support
fun <T> support(t : T){
}
I want to restrict this function to only accept classes other than Devil (all classes in the world, but not Devil). Something like
fun <T except Devil> support(t : T){
}
How do I do this in Kotlin? Is this even possible?
This is very likely an XY problem, so please do not apply this solution without considering something else.
One way to achieve this is to declare a non-generic overload of support() with the explicit type Devil, and deprecate that function with ERROR level:
fun <T> support(t: T) {
// do your stuff
}
#Deprecated("support() cannot be used with type Devil", level = DeprecationLevel.ERROR)
fun support(devil: Devil) {
error("NOPE.")
}
Note that this would also exclude subtypes of Devil - which is not explicitly stated in your question, but might be what you want.
However, nothing prevents users from working around it by explicitly calling the generic overload by specifying a type in <...>:
support<Devil>(Devil()) // compiles fine
support<Any>(Devil()) // compiles fine
Similarly, as #gidds pointed out, this approach also doesn't prevent compilation if you pass in a variable with a static type that is not Devil even if it holds an instance of Devil (because the compiler will choose the generic overload in that case):
val hiddenDevil: Any = Devil()
support(hiddenDevil) // compiles fine

How do I specify an ActionListener in Kotlin?

I want to add an ActionListener to a JButton in Kotlin. In Java, I would just write this:
JPanel makeButtonPanel() {
JPanel panel = new JPanel(new FlowLayout());
JButton dirButton = new JButton("Change directory");
dirButton.addActionListener(e -> chooseDirectory());
panel.add(dirButton)
return panel;
}
But it's not so simple in Kotlin. I first tried this:
private fun makeButtonPanel() : JPanel {
val panel = JPanel(FlowLayout())
val dirButton = JButton("Choose")
dirButton.addActionListener(e -> chooseDirectory()) // error message here
// ...
}
private fun chooseDirectory() { ... }
But I'm getting this error message:
Type Mismatch
Required: ((ActionEvent!) -> Unit)!
Found: KFunction1<ActionEvent, Unit>
I understand that the ! means that this is a java method with uncertain nullability, but that doesn't help me understand how to write it. All I want it to do is call the chooseDirectory() method. There must be a clean, simple way to do this, but I don't see it.
As you've discovered, you need to use braces ({ }).
This is because braces are a necessary part of defining a lambda in Kotlin.  (That differs from languages like Java and Scala, where the necessary part is the -> or => arrow.  That's because in Kotlin the arrow is optional if there are one or no parameters; if one, the it keyword is used.)
Without the braces, the code would call your chooseDirectory() function, and try to pass its result to addActionListener() — which obviously wouldn't work.
Braces are also sufficient: they're taken as defining a lambda unless you're giving the body of a function or method or an if/when branch.  (Again, this differs from most C/Java-like languages.  In Kotlin, if you just want a block scope, you have to use a construct such as run.)
As for the parentheses, they're optional here.  You could include them if you wanted:
dirButton.addActionListener({ chooseDirectory() })
But Kotlin has a convention that if a function's last parameter is a function, you can pass it after the parens:
dirButton.addActionListener(){ chooseDirectory() }
And if that would make the parens empty, then you can omit them entirely:
dirButton.addActionListener{ chooseDirectory() }
That's to allow functions that look like new language syntax.  For example, you may have met the with function:
with(someObject) {
itsProperty = someValue
}
That's just a perfectly ordinary function, defined in the standard library, and taking a function as its last parameter.  Similarly, repeat:
repeat(10) {
// Some code to be run 10 times…
}
There's one further thing worth mentioning here.  In Kotlin, lambdas are one way to define functions, which are first-class types and can be defined, passed around, and used just like other types.  This differs from Java, which has traditionally used interfaces for those purposes — often interfaces with a Single Abstract Method (‘SAM interfaces’) — and in which lambdas are little more than syntactic sugar for defining an anonymous implementation of such an interface.
As a special case, for interoperability, Kotlin allows a lambda to define an implementation of a Java SAM interface (or, since Kotlin 1.4, of a Kotlin fun interface), instead of a function.
ActionListener is a Java SAM interface, which is why you can use a lambda here.
Okay, I figured it out, and it was pretty simple. I just have to dispense with the parentheses and say
dirButton.addActionListener { chooseDirectory() }
I'm still not clear on when I should use braces instead of parentheses.

Use extension function from different context in Kotlin

Here is an example of what I'd like to achieve:
open class A {
open fun Int.foo() {
print("foo")
}
}
object B: A() {
val number = 5;
override fun Int.foo() {
print("overriden foo");
// I want to call the A.(Int.foo())
}
}
B.number.foo(); //outputs: "foooverriden foo"
First of all, does anything like this exist? Can I somehow assume number to be in the context of class A in its override method? How would I write this?
The more I think about it the more it twists my mind. Of course, you cannot call number.super.foo() because super for number is kotlin.Number. You cannot cast it to A because Int has nothing to do with A. The only way I can think about solving this to somehow import the extension function itself and rename it with as, but I cannot do that here since it is inside a class, so I cannot just import it. Any suggestions?
My use case for this is that I have a class where I manipulate some data, then in special cases, I want to manipulate it differently, but fall back to the original code as the last option. I could use normal functions instead of extension functions of course, but in my case, it comes natural to use extension functions, so I wanted to see if this could be achieved somehow.
It looks like this is impossible so far, I'm afraid.
There's an open issue for this on JetBrains' issue-tracking system: KT-11488.  There's a Kotlin work-around there, though that needs tweaks to the class designs.
(Also discussed on the JetBrains discussion board.  That mentions another workaround requiring a Java class.)
override fun Int.foo() {
print("overriden foo")
with (A()) {
foo()
}
}
Of course this is a bit of a hack and will get worse if A has some state which foo() depends on, which you'll then need to set manually.

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.

KClass::memberExtensionFunctions always be empty

Code
import kotlin.reflect.full.*
class FooBar(val bar: String)
fun FooBar.baz(): Unit {println(this.bar)}
fun main(args: Array<String>) {
FooBar::class.declaredMemberExtensionFunctions.forEach {
println(it)
}
FooBar::class.memberExtensionFunctions.forEach {
println(it)
}
}
Output is empty
This is because declaredMemberExtensionFunctions only returns extension functions that are declared inside a class (as seen in the docs) and FooBar.baz() is a top level declaration (So it is not declared inside FooBar.
class FooBar(val bar: String) {
fun FooBar.baz(): Unit {
println(this.bar)
}
}
While I imagine this is not what you want, structuring the extension function like this would make your main method output lines.
TLDR: You aren't going to be able to do this. Because extension functions can be declared everywhere, you are limited in what the reflection system can do for you.
There is a thread on kotlinlang.org that covers this exact question and why it is not possible.
Essentially, Kotlin's declaredMemberExtensionFunctions function is able to list extension functions which are declared as part of the class, not externally. The docs state:
Returns extension functions declared in this class.
And of course, memberExtensionFunctions behaves similarly:
Returns extension functions declared in this class and all of its superclasses.
Here's what #Yole says in that thread as to why this is not possible:
The task of finding all extension functions for Foo is equivalent to finding all methods which have Foo as the first parameter. Neither of these is possible without accessing every single class in your application through reflection.
#Yole is on here, he might be able to provide a more authoritative answer for you.