I have a class whose declaration is like :
class NetworkManagerImpl : NetworkManager { }
I wanted to make the class protected so that it is visible inside package only. But when i add protected in front of class like :
protected class NetworkManagerImpl : NetworkManager { }
It gives error as Modifier protected is not applicable inside file
How to fix this error or more importantly how to make an entire class(Top level) protected?
As written in the docs, there is no protected modifier for top-level entities like classes.
Here’s a statement coming from a Kotlin team member:
The motivation for not having package protected access is very simple: it does not provide any real encapsulation. Any other module in the system can define classes in the same package as your complex independent component and get full access to its internals. On the other hand, classes with internal visibility cannot be accessed from any module other than the one where they are defined.
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.
Kotlin has defined:
class CharRange : CharProgression, ClosedRange<Char>
but looking at CharProgression:
open class CharProgression : Iterable<Char>
there is no Progression interface. It directly implements Iterable.
Why doesn't Kotlin define a Progression interface as it has done with ClosedRange?
Maybe someone from JetBrains will correct me, but I would assume that the reason lies here:
// Auto-generated file. DO NOT EDIT!
import kotlin.internal.getProgressionLastElement
All this class hierarchy, including internal CharProgressionIterator is being auto-generated. Hence, being both internal and generated, it doesn't make much sense to have an interface nothing but the generated code would use.
The task is to hide Library1 interface1 behind the facade of Library2.
Full source here https://bitbucket.org/tim4dev/inheritance-interfaces/src/master/
(Library1) interface1
(Library2) interface2 : interface1
(Library2) Klass2: Interface2
(application)
implementation project(":library2")
class KlassApp constructor(
private val klass: Interface2
) {
fun klassAppFun() {
klass.interface1fun1()
}
}
We get an error
KlassApp.kt: Unresolved reference: interface1fun1
Question: what are the standard patterns to hide Library1 behind the facade of Library2 ?
You need to choose:
make Library1 an api dependency of Library2, not implementation as you currently have it (so not hide it fully);
if you want to hide it, you can't expose any types of Library1 in public parts of Library2, which includes extending its interfaces.
See the documentation for the difference of api and implementation:
So when should you use the api configuration? An API dependency is one that contains at least one type that is exposed in the library binary interface, often referred to as its ABI (Application Binary Interface). This includes, but is not limited to:
types used in super classes or interfaces
types used in public method parameters, including generic parameter types (where public is something that is visible to compilers. I.e. , public, protected and package private members in the Java world)
types used in public fields
public annotation types
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 have little doubt about adapter class. I know what's the goal of adapter class. And when should be used. My doubt is about class construction. I've checked some tutorials and all of them say that I should pass "Adaptee" class as a dependency to my "Adapter".
e.g.
Class SampleAdapter implements MyInterface
{
private AdapteeClass mInstance;
public SampleAdapter(AdapteeClass instance)
{
mInstance=instance;
}
}
This example is copied from wikipedia. As you can see AdapteeClass is passed to my object as dependency. The question is why? If I'm changing interface of an object It's obvious I'm going to use "new" interface and I won't need "old" one. Why I need to create instance of "old" class outside my adapter. Someone may say that I should use dependency injection so I can pass whatever I want, but this is adapter - I need to change interface of concrete class. Personally I think code bellow is better.
Class SampleAdapter implements MyInterface
{
private AdapteeClass mInstance;
public SampleAdapter()
{
mInstance= new AdapteeClass();
}
}
What is your opinion?
I would say that you should always avoid the new operator in a class when it comes to complex objects (except when the class is a Builder or Factory) to reduce coupling and make your code better testable. Off course objects like a List or Dictionary or value objects can be constructed inside a class method (which is probably the purpose of the class method!)
Lets say for example that your AdapteeClass is a Remote Proxy. If you want to use Unit Testing, your unit tests will have to use the real proxy class because there is no way to replace it in your unit tests.
If you use the first approach, you can easily inject a mock or fake into the constructor when running your unit test so you can test all code paths.
Google has a guide on writing testable code which describes this in more detail but some important points are:
Warning Signs for not testable code
new keyword in a constructor or at field declaration
Static method calls in a constructor or at field declaration
Anything more than field assignment in constructors
Object not fully initialized after the constructor finishes (watch out for initialize methods)
Control flow (conditional or looping logic) in a constructor
Code does complex object graph construction inside a constructor rather than using a factory or builder
Adding or using an initialization block
AdapteeClass can have one or more non-trivial constructors. In this case you'll need to duplicate all of them in your SampleAdapter constructor to have the same flexibility. Passing already constructed object is simpler.
I think creating the Adaptee inside the Adapter is limiting. What if some day you want to adapt a pre-existing instance?
To be honest though, I'd do both if at all possible.
Class SampleAdapter implements MyInterface
{
private AdapteeClass mInstance;
public SampleAdapter()
: base (new AdapteeClass())
{
}
public SampleAdapter(AdapteeClass instance)
{
mInstance=instance;
}
}
Let's assume you have an external hard drive with a regular USB port and you are trying to hook it up with a Mac which only has type-c ports. Yes, you can buy a new drive which has a type-c port but what about the data in it?
It's the same for the adapter pattern. There're times you initialize AdapteeClass with tons of flavors. When you do the conversion, you want to keep all the context.