Why sealed class User compiles successfully but sealed object User throws a compilation error?
I went through Kotlin docs but got nothing. I am playing a bit with Kotlin and just wanted to know the reason behind this?
sealed classes are supposed to be open, however all objects are final: sealed classes have a certain quantity of subclasses (inside the file, where the sealed class is declared), but objects are singletons, so they cannot have any subclasses. Consequently, sealed object declaration does not make any sense and can't be compiled.
Related
What is the difference between sealed and internal in Kotlin? I have read Kotlin's documentation on sealed classes and visibility modifiers; however, it is still not clear to me when to use sealed vs. internal. Maybe someone could provide real-world code samples?
Sealed classes | Kotlin & Visibility modifiers | Kotlin resources.
sealed class will be visible in all modules, but extendable only in the same module. This means if you have this:
sealed class MyClass {} then you can do this in the same module:
class MyExtensionClass: MyClass() {}
But you can't do the same thing in another module. But you can still use both MyClass and MyExtensionClass in another module.
For example you can do this in another module:
val x: MyClass = MyExtensionClass()
You can't instantiate a sealed class directly neither in the same or another module. This means you can't do this nowhere:
val x = MyClass()
So sealed class is basically an abstract class which can only be implemented in the same module.
internal class can be used and extended in the same module just like a sealed class, but you can do neither in another module. So you can't even use or instantiate it in another module. Also you can directly instantiate an internal class as long as you are doing it in the same module.
So: Use sealed to better control extending something. For example you create a library and you want a class from this library to be used but not extended. Use internal if you wan't your class to be invisible to other modules (you create a library, but certain class in this library shouldn't even be directly compile time usable by libraries users)
A good use case for sealed class:
You build a library and have some abstract class or interface which has multiple different implementations, but you want to make sure the libraries user doesn't add its own implementations (you wan't to be in control of implementation details).
A good use case for internal class:
You have some interface and a factory that creates implementations, but you don't want the implementing class to be compile-time visible to libraries users. They just use the factory and don't need to worry about the implementation. They might build their own implementation though and therefor not use the factory you provided and this is OK.
These are not mutually exclusive. You can have an internal sealed class as well.
internal is about visibility, and sealed is about inheritance rules.
internal means the class type is only visible within the module. In other modules, you can't even mention the name of the type.
sealed means it is open (can be subclassed), but subclasses (or implementations if it's a sealed interface) can only be defined in the same module, and the compiler keeps track of an exhaustive list of all subclasses. Another rule is that you can't create anonymous subclasses of it (object: MySealedClass). The advantage of a sealed type is that the compiler knows when you've exhaustively checked a type in when statements, if/else chains, etc. It can also be used in a library to ensure that only known implementations of a class or interface are ever passed to it (prevent users from creating subclasses of something and passing them into the library).
Bonus:
Visibility modifier keywords: public, internal, private, protected
Inheritance modifier keywords: open, final, sealed
data and value also cause a class to be final implicitly as a side effect.
The Kotlin documentation states:
A sealed class can have subclasses, but all of them must be declared in the same file as the sealed class itself. (Before Kotlin 1.1, the rules were even more strict: classes had to be nested inside the declaration of the sealed class).
Admittedly, this is worded as a necessary but not sufficient condition, but it does imply (by lack of anything contrary) that I can declare a subclass of a sealed class anywhere in the same file.
Given that the following code compiles:
//class Jungle {
sealed class Animal
class Tiger : Animal()
//}
why does the following not compile:
class Jungle {
sealed class Animal
class Tiger : Animal()
}
The second snippet gives the following errors with Intellij Kotlin plugin version 1.3.72-release-IJ2020.1-5:
Error:(3, 20) Kotlin: Cannot access '<init>': it is private in 'Animal'
Error:(3, 20) Kotlin: This type is sealed, so it can be inherited by only its own nested classes or objects
In fact, the second error message here seems to directly contradict the documentation.
There is an open issue for it that also notes the misleading diagnostic message. But it seems the conversation around it died down.
Also, this Sealed class inheritance proposal from 4 years ago leaves the matter of sub-classing a nested sealed class by a class on the same level as an open question
I included a library I'd like to use, but in accessing to one of its classes I get the error message,
"Cannot access '<init>': it is private in [class name]
Is there something I can do to rectify this on my side, or am I just stuck to not use the package?
The error means the constructor is private. Given your comment, I'm assuming you're using a library. If this is the case, you'll have to find a different way to initialize it. Some libraries have factories or builders for classes, so look up any applicable documentation (if it is a library or framework). Others also use the singleton pattern, or other forms of initialization where you, the developer, don't use the constructor directly.
If, however, it is your code, remove private from the constructor(s). If it's internal and you're trying to access it outside the module, remove internal. Remember, the default accessibility is public. Alternatively, you can use the builder pattern, factory pattern, or anything similar yourself if you want to keep the constructor private or internal.
I came across this issue when trying to extend a sealed class in another file. Without seeing the library code it is hard to know if that is also what you are attempting to do.
The sealed classes have the following unique features:
A sealed class can have subclasses, but all of them must be declared in the same file as the sealed class itself.
A sealed class is abstract by itself, it cannot be instantiated directly and can have abstract members.
Sealed classes are not allowed to have non-private constructors (their constructors are private by default).
Classes that extend subclasses of a sealed class (indirect inheritors) can be placed anywhere, not necessarily in the same file.
For more info, have a read at https://www.ericdecanini.com/2019/10/14/kotlins-sealed-class-enums-on-steroids/
Hopefully, this will help others new to Kotlin who are also encountering this issue.
Class constructors are package-private by default. Just add the public keyword before declaring the constructor.
By default constructor is public so need to remove internal keyword.
I'm autogenerating code with KotlinPoet and Auto Service. I didn't find any way to know if an annotated class has "internal" modifier so I can create another class with same modifier. For example:
#MyAnnotation
internal class Car
So I thought using Kotlin Reflection I would be able to get this information but no luck.
With the annotator processor I'm able to get the KClass but the visibility said "public":
Any clues on how to do it?
Kotlin reflection is not applicable during annotation processing. Kotlin reflection is for inspecting your code at runtime.
However there is a way to parse the metadata out of Kotlin class files, it's called kotlinx-metadata-jvm.
To use this in your annotation processor, you'll have to obtain the AnnotationMirror of the kotlin.Metadata annotation. From that mirror, obtain the annotation values and use them to construct the KotlinClassHeader as you can see in the examples for kotlinx-metadata-jvm. Once you are there you can use kotlinx-metadata-jvm to extract the flags for your class.
Kotlin's KClass has the visibility property, which can be KVisibility.INTERNAL.
Since internal is a visibility modifier, you should look for something related in the KClass API. The following will help you:
/**
* Visibility of this class, or `null` if its visibility cannot be represented in Kotlin.
*/
#SinceKotlin("1.1")
public val visibility: KVisibility?
Used like this: Car::class.visibility //INTERNAL
1) Singleton means the class have one instance. Having private constructer. No way to create object except reflection. No subclassing.
If i want to clone my singleton classthen class must and should implement Cloneable and override clone() right.
am not going to implement Cloneable interface in my Singleton class.
Then how cloning breaks my singleton. is this correct. Please clarify some one. if am wrong.
what is the need of throwing clonenotsupported exception.
No reason to implement Cloneable and override clone() to throw CloneNotSupportedException. Object. Clone, throws expectation when the Cloneable interface is absent.
The correct way to create singleton class using enums can be referred in my favorite java book "Effective Java" . Please read that.