I am trying to understand inline classes in kotlin
fun main(){
val password = Password("Current Password")
println(password)
println(password.password)
}
inline class Password(val password: String)
This is a sample code I wrote according to the documentation. Now they said no instantiation of class Password will happen.
My output should be
Current Password
Current Password
But I am getting
Password(password=Current Password)
Current Password
If instantiation doesn't happen, then when we try to access password variable directly we should access it as a common string right?
It's not compiled to an object so long as you don't use it in a nullable or generic context. If you do, it will get wrapped in an object just like the primitives do.
But the toString() and other functions and properties are still available to use as if it were a class, just like they are for primitives. I don't know the exact mechanism in compiled code, but I am guessing they are realized in the same way as extension functions (which on JVM are compiled as static methods with the "receiver" as another argument).
From your point of view, you still treat it exactly as any of the primitive classes, which have wrapper versions for when they are nullable or used as generics. But you have the added benefit of being able to override toString() and adding functions without using extensions.
Related
consider a SAM defined in Java
public interface Transform {
public String apply(String str);
}
This interface supports lambda to type conversion in Kotlin automatically
fun run(transform: Transform) {
println(transform.apply("world"))
}
run { x -> "Hello $x!!" } // runs fine without any issues
But now consider a Kotlin interface
interface Transform2 {
fun apply(str: String): String
}
Now the only way to invoke the run function would be by creating an anonymous instance of Transform2
run(object : Transform2 {
override fun transform(str: String): String = "hello $str!!"
})
but if we make the Transform2 interface a functional interface then the below is possible
run { str -> "hello $str!!" }
Why the Kotlin compiler cannot automatically type cast lambdas to matching interfaces (just as it does with Java interfaces) without needing to explicitly mark the said interfaces as a functional interface.
I've found some kind of a rationale in a comment in KT-7770:
... treating all the applicable interfaces as SAM might be too
unexpected/implicit: one having a SAM-applicable interface may not
assume that it will be used for SAM-conversions. Thus, adding another
method to the interface becomes more painful since it might require
changing syntax on the call sites (e.g. transforming callable
reference to object literal).
Because of it, current vision is adding some kind of modifier for
interfaces that when being applied:
Adds a check that the interface is a valid SAM
Allows SAM-conversions on call sites for it
Something like this:
fun interface MyRunnable {
fun run()
}
Basically, he is saying that if the SAM conversion were done implicitly by default, and I add some new methods to the interface, the SAM conversions would no longer be performed, and every place that used the conversion needs to be changed. The word "fun" is there to tell the compiler to check that the interface indeed has only one abstract method, and also to tell the call site that this is indeed a SAM interface, and they can expect the author to not suddenly add new abstract methods to the interface, suddenly breaking their code.
The thread goes on to discuss why can't the same argument can't be applied to Java, and the reason essentially boils down to "Java is not Kotlin".
This is speculation, but I strongly suspect one reason is to avoid encouraging the use of functional interfaces over Kotlin's more natural approach.
Functional interfaces are Java's solution to the problem of adding lambdas to the Java language in a way that involved the least change and risk, and the greatest compatibility with what had been best practice in the nearly 20 years that Java had existed without them: the use of anonymous classes implementing named interfaces. It needs umpteen different named interfaces such as Supplier, BiFunction, DoublePredicate… each with their own method and parameter names, each incompatible with all the others — and with all the other interfaces people have developed over the years. (For example, Java has a whole host of interfaces that are effectively one-parameter functions — Function, UnaryOperator, Consumer, Predicate, ActionListener, AWTEventListener… — but are all unrelated and incompatible.) And all this is to make up for the fact that Java doesn't have first-class functions.
Kotlin has first-class functions, which are a much more general, more elegant, and more powerful approach. (For example, you can write a lambda (or function, or function literal) taking a single parameter, and use it anywhere that you need a function taking a single parameter, without worrying about its exact interface. You don't have to choose between similar-looking interfaces, or write your own if there isn't one. And there are none of the hidden gotchas that occur when Java can't infer the correct interface type.) All the standard library uses function types, as does most other Kotlin code people write. And because they're so widely-used, they're widely supported: as part of the Kotlin ecosystem, everyone benefits.
So Kotlin supports functional interfaces mainly for compatibility with Java. Compared to first-class functions, they're basically a hack. A very ingenious and elegant hack, and arguably a necessary one given how important backward compatibility is to the Java platform — but a hack nonetheless. And so I suspect that JetBrains want to encourage people to use function types in preference to them where possible.
In Kotlin, you have to explicitly request features which improve Java compatibility but can lead to worse Kotlin code (such as #JvmStatic for static methods, or casting to java.lang.Object in order to call wait()/notify()). So it fits into the same pattern that you also have to explicitly request a functional interface (by using fun interface).
(See also my previous answer on the subject.)
I'm wondering what is the best way to structure functional code in Kotlin.
I don't want to create unnecessary objects (and put functions in a closed scope) to group my functions with. I heard I can group functions by packages and put them in the top level of a package. I've also seen in Arrow library that functions are grouped in interface companion objects as extension functions and this looks the best except the fact I need to create a companion object.
Object way:
object Container {
fun myFunc() = ...
}
...
Container.myFunc()
Package way:
package myPackage
fun myFunc() = ...
...
myPackage.myFunc()
Arrow way:
interface Container {
companion object {
fun Container.myfunc() = ...
}
}
...
Container.myFunc()
What is the best way to structure my functions and group them using Kotlin? I want to keep a pure functional style, avoid creating any sort of objects, and be able to easily navigate to functions by namespaces like:
Person.Repository.getById(id: UUID)
If I understand you correctly, you're looking for the concept of namespaces (structured hierarchical scope for accessing symbols).
Kotlin does not support namespaces, but as you found out, there are different ways of having similar functionality:
object declarations. They pretty much fulfill the needs, however they lead to creation of an actual object in JVM and introduce a new type, which you don't need. The Jetbrains team generally discouraged the use of objects as namespaces, but it's of course still an option. I don't see how companion objects inside interfaces add any value. Maybe the idea is to limit the scope to classes which implement the interface.
Top-level functions. While possible, top-level functions in Kotlin pollute the global namespace, and the call-site does not let you specify where they belong. You could of course do workarounds, but all of them are rather ugly:
Fully qualify the package com.acme.project.myFunc()
Use a deliberately short, but no longer domain-representing package functional.myFunc()
Call function without package, but with prefix package_myFunc()
Extension functions. If the functionality is closely related to the objects it's operating on, extension functions are a good option. You see this for the Kotlin standard collections and all their functional algorithms like map(), filter(), fold() etc.
Global variables. This does not add much over the object approach, just prevents you from introducing a named type. The idea is to create an anymous object implementing one or more interfaces (unfortunately, without interfaces the declared functions are not globally accessible):
interface Functionals {
fun func(): Int
}
val globals = object : Functionals {
override fun func() = 3
}
It is mainly handy if your object implements different interfaces, so that you can pass only a part of the functionality to different modules. Note that the same can be achieved with objects alone, as they can implement interfaces too.
I am implementing an interface of a third party library(java). I am overriding a function with the following signature:
override fun onCallback(name: String?) {
}
I can change to the following without the compiler complaining:
override fun onCallback(name: String) {
}
What is the effect of this? What happens if the underlying library calls onCallback(null)?
Types coming from Java are platform types (in this case, this parameter has a type of String!. If the parameter is not annotated in Java, it's up to you to decide whether it can ever have a null value, and you have to mark the type of the parameter in Kotlin accordingly. If you mark it as non-nullable, but Java code passes null to it, you'll get an exception at runtime - Kotlin generates checks for parameters like this, which you can look at by decompiling the generated bytecode.
Also see the official docs about null safety and platform types for more detail.
I often see the #InlineOnly annotation when browsing Kotlin's stdlib. As far as I recall the annotation only happens to be on inline functions. What is the purpose of this annotation? Isn't it obvious that inline functions are always inlined? It's documentation isn't really helpful
Specifies that this function should not be called directly without inlining
Is it possible for inline functions to be called not inline?
To quote an answer found here:
InlineOnly means that the Java method corresponding to this Kotlin
function is marked private so that Java code can not access it (which
is the only way to call an inline function without actually inlining
it).
This annotation is internal only because
This annotation was added in the last moment before release, so we hadn't time to validate the design and decided to keep it internal for a while. There are good chances we make it public later.
When programming C++ we used to create copy constructors when needed (or so we were taught). When switching to Java a few years ago, I noticed that the Cloneable interface is now being used instead. C# followed the same route defining the ICloneable interface. It seems to me that cloning is part of the definition of OOP. But I wonder, why were these interfaces created, and the copy constructor seems to have been dropped?
When I thought about it, I came to the thought that a copy constructor would not be useful if one needs to make a copy of an object whose type is not known (as in having a reference to a base type). This seems logical. But I wonder whether there are other reasons that I do not know of, for which the Cloneable interfaces have been favored over copy constructors?
I think it's because there is no such inherent need for a copy constructor in Java and in C# for reference types. In C++ objects are named. You can (and you will most often) copy (and in C++1x move) them around e.g when returning from functions, since returning pointers require you to allocate dynamic memory which would be slow and painful to manage. The syntax is T(x) so it makes sense to make a constructor taking a T reference. C++ couldn't make a clone function, since that would require returning an object by value again (and thus another copy).
But in Java, objects are unnamed. There are only references to them, which can be copied, but the object itself isn't copied. For the cases when you actually need to copy them, you can use the clone call (but i read in other anwers clone is flawed. i'm no java programmer so i cannot comment that). Since not the object itself is returned, but rather a reference to it, a clone function will suffice. Also a clone function can be overriden. That's not going to work with copy constructors. And incidentally, in C++ when you need to copy a polymorphic object, a clone function is required too. It's got a name, the so-called virtual copy constructor.
Because C++ and Java (and C#) aren't the same thing. C++ has no built-in interfaces because interfaces aren't part of the language. You can fake them with abstract classes but they aren't how you think about C++. Also, in C++ assignment is normally deep.
In Java and C# assignment just involves copying the handle to the internal object. Basically when you see:
SomeClass x = new SomeClass();
in Java or C#, there's a level of indirection builtin that doesn't exist in C++. In C++, you write:
SomeClass* x = new SomeClass();
Assignment in C++ involves the dereferenced value:
*x = *another_x;
In Java you can get access to the "real" object as there is no dereference operator like *x. So to do a deep copy, you need a function: clone(). And both Java and C# wrapped that function into an interface.
It's the issues of final type and of cascading the clone operation through the super classes which is not addressed by copy constructors - they are not extensible. But the Java clone mechanism is widely considered badly broken too; especially problems where a subclass does not implement clone(), but inherits from a superclass that implements cloneable.
I strongly recommend you research cloning carefully, whatever path you choose - you will likely choose the clone() option, but make sure you know exactly how to do it properly. It's rather like equals() and hashCode() - looks simple on the surface, but it has to be done exactly right.
I think you haven't get the right point. I give you my two cents.
Fundamentally there's a problem: creating a clone of a class without knowing the exact class type. If you use copy constructor, you cannot.
Here is an example:
class A {
public A(A c) { aMember = c.aMember }
int aMember;
}
class B : A {
public B(B c) : base(c) { bMember = c.bMember }
int bMember;
}
class GenericContainer {
public GenericContainer(GenericContainer c) {
// XXX Wrong code: if aBaseClass is an instance of B, the cloned member won't
// be a B instance!
aBaseClass = new A(c.aBaseClass);
}
A aBaseClass;
}
The Clone method, if declare virtual, could create the right class instance of the generic member.
An this problem is common to every language, C# C++ or Java...
Maybe this is what you was meaning, but I cannot understand this from any answer.
Just wanted to add that in Java the copy constructor is not completely useless.
There are cases where your class has a private instance variable of a mutable non-final type, e.g. Date, and has a setter and getter for the variable. In the setter, you should make a copy of the given date, because the caller could modify it later and thereby manipulate your object's internal state (usually by accident, but maybe intentional). In the getter, the same precaution is required.
The defensive copy could be implemented by calling clone() (the class Date is cloneable), but a malicious caller could call the setter with a subclass of Date which overrides the clone() method with {return this;}, and so the caller might still be able to manipulate your object. This is where the copy constructor comes into play: By calling new Date(theDate), you are sure to get a fresh Date instance with the same timestamp as the given date, without any connection between the two date instances. In the getter, you could use the clone method, because you know the private variable will be of class Date, but for consistency, usually the copy constructor is used there, too.
Also note that the copy constructor would note be required if the Date class was final (calling clone() were safe) or immutable (no copy required).
I think its only because once u have defined a copy constructor, you could never pass the reference itself again. (Unless it would have a function that does that...but thats not any easier than using the clone() method.)
In C++ its not a problem: you can pass the whole object or its reference.