Why can't we have public typealiases from private expanded types? - kotlin

If I try this:
sealed class Attributes
data class Attributes1(
val prop1: String
) : Attributes()
private data class IMyType<A>(
val attributes: A
) where A: Attributes
typealias MyType1 = IMyType<Attributes1>
...I get the error: 'public' typealias exposes 'private' in expanded type IMyType.
What is/are the reason(s) for preventing this?
Note: Using Kotlin 1.1.4
Edit 1
I understand what typealiases are and I understand the implications of the restrictions in place.
What I'm asking is why those restrictions need to be there.
If you consider my example code... I want MyType1 (and maybe others) to be accessible outside of this file, but I don't want the raw/generic IMyType to be used outside of this file.
Is that not a legitimate use case?

By definition typealias is to provide an alternative name for the existing type. So you can't promoting the visibility for the existing type by typealias.
From the grammar of the typealias, if you want to use typealias in your code, you must make sure the visibility of the typealias is lower or equals than the visibility of the existing type. for example:
internal class Bar
private typealias PrivateFoo = Bar
internal typealias InternalFoo = Bar
//v--- error
public typealias PublicFoo = Bar

The visibility of the type alias should be the same or more restricted as the corresponding type.
When you declare IMyType as private in your file, IMyType is a file-private class which can be accessed only within that kotlin file. If you declare the public type alias MyType1 for IMyType, then it is meaningless for IMyType to be private since MyType1 can be access everywhere. So, it is forbidden.
From Kotlin's doc:
Type aliases do not introduce new types. They are equivalent to the corresponding underlying types. When you add typealias Predicate<T> and use Predicate<Int> in your code, the Kotlin compiler always expand it to (Int) -> Boolean.
The main purpose of having typealias is to provide alternative name for existing types. In your case, both IMyType and MyType1 refer to the same class. You cannot access IMyType through MyType1 outside the file since IMyType intends to be private.
Example to show new type is not introduced:
//Kotlin code
fun acceptMyType1(type: MyType1) {}
//Decompiled code, MyType1 is not used
public static final void acceptMyType1(#NotNull IMyType type) {
Intrinsics.checkParameterIsNotNull(type, "type");
}
Sidetracked problem: You cannot expose a private super class through a public sub class also.

Related

Easiest way to modify value passed to inline class constructor

I'm trying to use inline classes in Kotlin to create a class inlining the String class, such that if I have an instance of my class that it will always be true for the contained string that s == s.trim().
I was initially expecting there to be a straightforward way to do this, like perhaps:
#JvmInline
value class Trimmed private constructor(val str: String) : {
constructor(s : String) : super(s.trim())
}
but that doesn't work, and neither do the other direct approaches I considered ("this(s.trim())", etc.).
This problem has turned out to be surprisingly tricky:
Kotlin seems to provide no easy way to have the primary constructor filter or modify the data that is passed to the constructor of the contained String object.
Even if I make the primary constructor private, I can't declare another constructor with the same signature (taking a single String as a parameter).
If this were a normal (non-inlined) class, I could just set the value after superclass class construction (e.g. "init { str = str.trim() }", but since it's an inline class, I can't do that. ("this=this.trim()" doesn't work either, and String objects themselves are immutable so I can't change the contents of 'str'.)
I tried making the class constructor private and creating a factory function in the same file with the same name as the class, but then I couldn't call the class constructor from within the factory function due to access restrictions.
I then tried making the factory function within the class's companion object, but then Kotlin tried to make that function call itself recursively instead of calling the class's constructor. I wasn't able to find a way to syntactially disambiguate this. I managed to work around this by creating a file-private typealias to give another name for the class so I could call the constructor from within the factory function. (Annoyingly, I couldn't declare the typealias in the companion object next to the factory function: I had to declare it outside.)
This worked, but seemed ugly:
typealias Trimmed2 = Trimmed
#JvmInline
value class Trimmed private constructor(val str: String) {
init { assert(str == str.trim()) }
companion object {
// Kotlin won't let me put the typealias here. :-(
fun Trimmed(s: String): Trimmed = Trimmed2(s.trim()) // Don't want recursion here!
}
}
Another working solution is here, using a private constructor with a dummy argument. Of course Kotlin complained that the dummy argument was unused and so I had to put in a big (why is it so big?) annotation suppressing the warning, which is, again, ugly:
#JvmInline
value class Trimmed private constructor(val str: String) {
private constructor (untrimmed: String, #Suppress("UNUSED_PARAMETER") dummy: Unit) : this(untrimmed.trim())
init { assert(str == str.trim()) }
companion object {
fun Trimmed(s: String): Trimmed = Trimmed(s, Unit)
}
}
Is there a simpler, cleaner way to do this? For instance, a syntactic way to clarify to Kotlin that the companion function is trying to call the class constructor and not itself and so avoid the need for a dummy parameter?
Goals:
Code to construct instances of the class from outside this file should look like constructing an instance of a normal class: 'Trimmed("abc")', not using some factory function with a different name (e.g. "of" or "trimmedOf") or other alternate syntax.
It should be impossible to construct the object containing an untrimmed string. Outside code, and the Trimmed class itself, should be able to trust that if a Trimmed instance exists, that its contained str will be a trimmed string.

Kotlin constructor val vs private val

If I have something like the following:
interface IRecordService {
fun doSomething () : Record
}
#MongoRepository
interface IRecordRepository : MongoRepository<Record, String> {
}
#Service
class RecordService (
private val recordRepository : IRecordRepository // or just val instead of private val
) : IRecordService
{
override fun doSomething () : Record {
// does something
}
}
Is there any difference between using private val in the RecordService constructor vs just val? I've seen both being used but couldn't tell if there was a recommended way or why.
This isn't specific to Spring or Mongo; it's just core Kotlin. There are several things going on here; I'll try to unpick them.
Consider the simpler definition:
class MyClass(i: Int)
The parens specify the primary constructor: any parameters there (such as i) are passed into the class, and are available during construction. So you could pass them up to the superclass constructor, use them in property initialisers, and/or in an init block:
class MyClass(i: Int) : MySuperclass(i) {
val someProperty = i
init {
println("i is $i")
}
}
However, they don't persist after the instance has been constructed — so you couldn't refer to them in methods, or from outside the class.
If you want to do that, you have to define a property for each parameter you want to persist. You could do that explicitly, e.g.:
class MyClass(i: Int) {
val i2 = i
}
Here every instance of MyClass has a property called i2 which is initialised to the i constructor parameter.
However, because this is a common pattern, Kotlin provides a shortcut. If you specify val or var in the primary constructor:
class MyClass(val i: Int)
then Kotlin creates a property with the same name as the parameter, and initialises it for you. So every instance of the above class has a property called i that you can refer to at any time.
By default, properties in Kotlin are public: you can access them from inside the class, from subclasses, from other classes in the same module, and from any other code that has a MyClass instance.
However, in some cases it's useful to restrict access, so you can add a visibility modifier: internal prevents code in other modules from seeing it, protected allows only subclasses to see it, and private makes it visible only inside the class itself.
So, to answer your question: without the private modifier, any code that had access to your RecordService would be able to access its recordRepository property; adding private prevents that, and means that only code within RecordService can see it.
In general, it might be a good idea to centralise all access to the recordRepository in the one class; then making it private would ensure that no other code can muck around with it. That would make it easier to see what's going on, easier to debug, and safer to work on. (However, we obviously don't know about the rest of your program, and can't advise on whether that would be a good plan in your case.)
By the way, using an I prefix for interfaces is not a convention that's used much in Kotlin (or Java). There's often little point in having an interface with only one implementation; and if you could have multiple implementations, then better to use a simple term for the interface and then more specific terms for the implementations.  (For example: the List interface with ArrayList and LinkedList classes, or Number with Int and Long.)
If you put val, it will be a constructor parameter and property. If you don't, it will be a constructor parameter (NOT property).
See Why to put val or var in kotlin class constructors
Firstly if you use val it converts this constructor parameter to property,If you do not want to hide this property (to set it) from other classes,you can use val.But if you do not want your property to be changed by other classes you should use private val instead.
Well, you can use both val and private val in your constructor there's no problem in that, it's just that with private keyword your properties wont be modified or accessed by some other class, so it basically provides some data hiding. If you talking about difference in functionality inside your RecordService class, then no there wont be any difference.

Kotlin: Difference between constant in companion object and top level

The general pattern to create constants in Kotlin seems to be using companion objects. However, I can also define a constant at the file level. Why is that not so popular? Am I missing something?
With companion object:
class Example {
companion object {
const val CONSTANT = "something"
}
On top level:
const val CONSTANT = "something"
class Example {
}
In Java you're forced to put all static field and method declarations in a class and often you even have to create a class just for that purpose. Coming to Kotlin, many users look for the equivalent facility out of habit and end up overusing companion objects.
Kotlin completely decouples the notions of a file and a class. You can declare any number of public classes in the same file. You can also declare private top-level functions and variables and they'll be accessible only to the classes within the same file. This is a great way to organize closely associated code and data.
Compared to top-level declarations, the syntax of companion objects is quite unwieldy. You should use them only when you specifically want to associate some public static code or data with a class and want your users to qualify access to it with the class's name. The use cases for this are quite rare and in most cases the top-level declarations are more natural.
Whenever you have some private static code/data that you want to couple to a class, you'll be better served with private top-level declarations.
Finally, sometimes the concern of the generated bytecode matters. If, for whatever reason, you have to produce a Java class with Kotlin code such that the class has a static member, you must resort to a companion object and a special annotation.
Differences in usage
Defining the field in a companion object limits the scope it is available in without importing to only that class, which can help keeping the data from being used in unexpected places.
Defining in the file makes the field available to any code in the same package as the field.
Differences in Bytecode
const val CONSTANT = "something"
class Example {
}
Creates the following:
Example.java
public final class Example {}
XKt.java
import kotlin.Metadata;
import org.jetbrains.annotations.NotNull;
public final class XKt {
public static final String CONSTANT = "something";
}
Whereas:
class Example {
companion object {
const val CONSTANT = "something"
}
}
Creates the following:
public final class Example {
public static final String CONSTANT = "something";
public static final Example.Companion Companion = new Example.Companion((DefaultConstructorMarker) null);
public static final class Companion {
private Companion() {}
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
I think that basically depends on whether you want that constant to be part of a class. If you put it inside a companion object, it will be accessed like this:
Example.CONSTANT
If you choose to put a constant on file level, it will be imported from other files and accessed with simply CONSTANT normally.
There are reasons for putting constants in classes as well as for putting them top-level.
Note that the const keyword can only be applied to variables of type String or primitive types (Int etc.) (reference). For most cases though, there's no need to apply the keyword. Defining constant values as shown in the following works as well:
val constantFIS = FileInputStream("path")
Sometimes you actually need to put constant outside of companion object. Apparently constants in companion objects are not that “that much” constant as one would suppose. For instance:
internal const val MY_FOO = "It's my ${Foo.FOO}";
open class Foo {
internal companion object {
const val FOO = "foo";
}
}
#Kaboom(name=MY_FOO)
open class Bar {}
Above code is not compiling. As long some “constans” are part of companion objects, they're not really constants. But when you move FOO outside of companion object, everything works.
On the other hand I'd like the compiler to do the work for me and to find out if it is possible to functionally turn some static final field to a constant or not. Why should I put my effort and time to decide what is or is not a literal constant for the compiler? It is just wrong.

Why the modifier on property is the same as Getter and Setter but not Field after Java being translated into Kotlin?

Official Ref says the default Visibility Modifier is public.
But from koan data classes it can be inferred that it is private.
Is it a contradiction? What is the default Visibility Modifier of property in kotlin?
---------The above is the initial question---------------
I didn't mix property and field up. But I did have confusion on how property is accessed.
To resolve my confusion, I actually should have asked the new question in edited title.
Self-answered below.
The default visibility for properties (and functions and classes, and...) is indeed public.
The Koan is a little confusing, because the Java class has private fields with public getters.
A property can be seen as the combination of field, a getter and an optional setter. The property in the Koan has a private backing field and a public getter.
If you for example write
val age = person.age
then Kotlin will basically generate a getAge() method of the Person class, that will be called internally. This method returns the field itself.
It's also possible to add behavior to that getter. You can find more info in that in the documentation.
It's therefore not a contradiction, but a different concept.
What it the default Visibility Modifier for properties in kotlin?
It is public, as the docs say
Why are the fields not private
In this example the fields are immutable, so there are no setters defined automatically. The data class automatically has getters, and uses them, but it simplifies reading the code by not requiring them to be manually called.
Worked example
This code:
object X {
data class Example(val a: String, val b: String)
#JvmStatic
fun main(args: Array<String>) {
val e = Example("a", "b")
println(e.a)
println(e.b)
}
}
The main method of this compiles to this (with checks and metadata removed):
public static final void main(String[] args) {
X.Example e = new X.Example("a", "b");
String var2 = e.getA();
System.out.println(e.getA());
var2 = e.getB();
System.out.println(var2);
}
(Decompiled using IntelliJ IDEA)
Property encapsulates backing field by defintion. Backing field is directly assigned only when being initialized. All accesses except initialization are done through accessors.
So the private modifier on field in Java is no longer needed in Kotlin.
And the public on getter and setter in Java is placed on property(actually, still for getter and setter) in Kotlin.
Therefore the omitted modifier is public and not private.

Restrict Constructor Access

I have a type like this
sealed class Foo[A](val value: A)
object Foo {
def apply[A](v: A)(implicit num: Numeric[A]): Foo[A] =
/* highly complex stuff to make a Foo[A] */
implicit def toA[A](x: Foo[A]) = x.value
}
Foo as a class is only supposed to hold the value, so an implicit Numeric would not make much sense. But I need the type of A to be always a numeric.
So my idea is to just make it impossible to use Foos normal constructor outside of its companion. Is that possible in Scala?
Yeah, since the companion object can access private members of its companion class you can just make the primary (and auxiliary if any) constructor private.
Pseudo code here:
class ConcreteFoo private (n: Int) extends Foo(n)