Kotlin inner/nested class instantiable only from parent - kotlin

Is it possible to translate the following Java snippet into Kotlin? Maintaining guarantees offered by the access modifiers
public class Outer {
public Inner newInner() {
return new Inner();
}
public static class Inner {
private Inner() { }
}
}

Here is an idea I thought of. It could be considered slightly abusing abstract/sealed classes:
class Outer {
fun newInner(): Inner = PrivateInner()
sealed class Inner { // abstract class also works, but you allow subclassing from everywhere
init {
if (this !is PrivateInner) {
throw IllegalStateException("Do not subclass Outer.Inner!")
}
}
// implementations go here
}
private class PrivateInner: Inner()
}
A note on subclassing:
I used a runtime check to prevent people from subclassing Outer.Inner and instantiating the subclass. Unfortunately with this method, you cannot fully prevent subclassing, and preventing the instantiation of invalid subclasses can only be done at runtime.
A (weak) way to prevent subclassing is to use a sealed class. Making Outer.Inner sealed prevents subclassing from anywhere that is outside Outer's package.

Related

How do you do qualified superclass constructor invocation in Kotlin?

I'm using Kotlin and Java together. I am looking for a way to extend a non-static nested class from Kotlin, but I have no idea how to do it.
From the JLS 1.8:
Example 8.8.7.1-1. Qualified Superclass Constructor Invocation
class Outer {
class Inner {}
}
class ChildOfInner extends Outer.Inner {
ChildOfInner() { (new Outer()).super(); }
}
I've tried to do like below but it doesn't really work in Kotlin:
class ChildOfInner(): Outer().Outer.Inner()
Using Kotlin we can inherit inner classes in this way:
class ChildClass : Outer() {
inner class ChildOfInner : Outer.Inner() {
}
}
So firstly we must inherit Outer class and then we are able to inherit Inner class.

Overriding Dart methods with Generics arguments

I have this case where I am extending from a super class with methods being typed using Generics as the following:
Models
abstract class SuperClass {
//.....
}
class SubClass extends SuperClass {
int a;
int b;
String c;
//....
}
Controllers
abstract class A {
T getDoc<T extends SuperClass>(T doc);
}
class B extends A {
T getDoc<T extends SubClass>(T doc) { //<================ Error
//....
}
}
Basically class B will only deal with a SubClass model and any class that extends it. Extending SuperClass is not enough. It's a way to enforce the type usage. I could add a helper function that will check the type for each method within class B (doc is SubClass) but seems like a lot repetition.
But the above architecture fails when overriding the method getDoc in class B saying that it isn't a valid override although SubClass is a SuperClass. How can I achieve something like this? Or is there a better way of doing it? Appreciate any pointers :)
I have finally a found a way :)
So I wanted the class B's methods to accept exclusively types that extend SubClass, but class A method's signature expects parameters extending class SuperClass.
To go about this I did the following:
Models
abstract class SuperClass {
//.....
}
class SubClass extends SuperClass {
int a;
int b;
String c;
//....
}
Controllers
abstract class A<K extends SuperClass> {
T getDoc<T extends K>(T doc);
}
class B extends A<SubClass> {
T getDoc<T extends SubClass>(T doc) {
//.......
}
}
can you use covariant modifier.
In your example:
abstract class A {
T getDoc<T extends SuperClass>(covariant T doc);
}
Check: https://github.com/dart-lang/sdk/blob/master/docs/language/informal/covariant-overrides.md
You can not narrow the generic type argument. Class B guaranties (by extending class A), that it will/can handle all type arguments (and sub types!), that class A can handle. Consider the following situation:
class OtherSubClass extends SuperClass {
//....
}
void main() {
var b = B();
b.getDoc(OtherSubClass());
}
What would you expect to happen? Class B is not able to handle objects of type OtherSubClass, so it breaks the contract with class A.

Base class or Abstract class without abstract method

I have a problem to chose the between an abstract class without abstract methods OR a base class with an interface.
I have two implementation in my mind:
1.
Let's say I have a AbstractRenderer:
abstract class AbstractRenderer
{
protected $shape;
public function __construct(AbstractShape $shape)
{
$this->shape = $shape;
}
public function render(): string
{
return $this->shape->generate()->asArray();
}
}
and the WebRenderer would be like this:
class WebRenderer extends AbstractRenderer
{
}
2.
Have a base class and an interface like this:
Interface InterfaceRenderer
{
public function __construct(AbstractShape $shape);
public function render(): string;
}
and a base class that impediments the interface:
class BaseRenderer implements InterfaceRenderer
{
protected $shape;
public function __construct(AbstractShape $shape)
{
$this->shape = $shape;
}
public function render(): string
{
return $this->shape->generate()->toString();
}
}
again, my WebRenderer would be like this:
class WebRenderer extends BaseRenderer
{
}
I don't know which is the correct implementation, or there is a better way to implement this and what is the pros and cons of each.
Thanks
From the Renderer client’s perspective the 2 solutions are basically identical. As long as they depend on an abstract object (interface or an abstract class), you’ll have benefits of polymorphism. You’d lose those if you make them depend on WebRenderer (concrete object).
Interface’s benefits over abstract classes
doesn’t occupy inheritance
no fragile base class problem
Abstract classes provide
static methods (in many languages interface can’t have these)
protected implementation

What is the difference between 'open' and 'public' in Kotlin?

I am new to Kotlin and I am confused between open and public keywords. Could anyone please tell me the difference between those keywords?
The open keyword means “open for extension“ - i.e. it's possible to create subclasses of an open class:
The open annotation on a class is the opposite of Java's final: it allows others to inherit from this class. By default, all classes in Kotlin are final, which corresponds to Effective Java, Item 17: Design and document for inheritance or else prohibit it.
You also need to be explicit about methods you want to make overridable, also marked with open:
open class Base {
open fun v() {}
fun nv() {}
}
The public keyword acts as a visibility modifier that can be applied on classes, functions, member functions, etc. If a top-level class or function is public, it means it can be used from other files, including from other modules. Note that public is the default if nothing else is specified explicitly:
If you do not specify any visibility modifier, public is used by default, which means that your declarations will be visible everywhere
class A { ... } in Java is equal to open class A { ... } in Kotlin.
final class B { ... } in Java is equal to class B { ...} in Kotlin.
It is not related with public.
In Kotlin, everything without access modifiers is public by default. You can explicitly say public in the definition, but it is not necessary in Kotlin.
So,
public class A { ... }
and
class A { ... }
are the same in Kotlin.
I put here just for my memo, maybe useful for someone else :
open class in kotlin means that a class can be inherited because by default they are not:
class Car{....}
class Supercar:Car{....} : // give an error
open Car2{....}
class Supercar:Car2{....} : // ok
public class in Java is about the visibility of class (nothing to do with inheritance : unless a class in java is final, it can be inherited by default).
In kotlin all the class are public by default.
open method in kotlin means that the method can be overridden, because by default they are not.
Instead in Java all the methods can be overridden by default
The method of an open class cannot be overridden by default as usual (doesn't matter if the class is open), they must be declared that they can be overridden :
open class Car{
fun steering{...}
}
class Supercar:Car{
override fun steering {...} // give an error
}
open class Car2{
open fun steering{...}
}
class Supercar:Car2{
override fun steering {...} // ok
}
for more details : https://kotlinlang.org/docs/reference/classes.html
public: public keyword in Kotlin is similar to java it is use to make the visibility of classes, methods, variables to access from anywhere.
open: In Kotlin all classes, functions, and variables are by defaults final, and by inheritance property, we cannot inherit the property of final classes, final functions, and data members. So we use the open keyword before the class or function or variable to make inheritable that.
open is opposite to Final in java.
If the class is not 'open', it can't be inherited.
class First{}
class Second:First(){} // Not allowed. Since 'First' is Final(as in Java) by default. Unless marked "open" it can't be inherited
Don't get confused with open and public. public is a visibility modifier
class Third{} // By default this is public
private class Fourth{}
class Fifth{
val third = Third() // No issues
val fourth = Fourth() // Can't access because Fourth is private
}
All classes, methods, and members are public by default BUT not open
Keyword open in kotlin means "Open for Extension"
means if you want any class to be inherited by any subclass or method to be overriden in subclasses you have to mark as open otherwise you will get compile time error
NOTE: abstract classes or methods are open by default you do not need to add explicitly.
OPEN VS FINAL VS PUBLIC
OPEN :
child class can access this because they are inherited by its parent.
In Kotlin you need to add 'open' keyword unlike java whose all classes are 'open' by default
Example :
Kotlin : open class A () {}
Java : class A () {}
FINAL :
child class can't access or inherit.
In JAVA you need to add 'final' keyword unlike kotlin whose all classes are 'final' by default
Example :
Kotlin : class A () {}
Java : final class A () {}
PUBLIC : Any class whether its inherited or not can access its data or methods.
Example in Kotlin :
//Final
class DemoA() {
protected fun Method() {
}
}
class DemoB() : DemoA {
Method() // can't access
}
//OPEN
open class DemoA() {
protected fun Method() {
}
}
class DemoB() : DemoA {
Method() // can access
}
//Public
class DemoA() {
fun Method() {
}
}
class DemoB() {
val a = DemoA()
a.Method() // can access
}
Example in Java :
//FINAL
final class DemoA() {
protected void name() {
}
}
class DemoB() extends DemoA {
name(); // Can't access
}
//Open
class DemoA() {
protected void name() {
}
}
class DemoB() extends DemoA {
name(); // Can access
}
//Public
class DemoA() {
void name() {
}
}
class DemoB(){
DemoA a = new DemoA()
a.name(); // Can access
}
Summarized answer (Kotlin)
The defaults of declarations of classes, methods, and properties are
(public + final). final prevents any inheritance attempts.
In order to be able to extend a class, you must mark the
parent class with the open keyword.
In order to be able to override the methods or properties, you must
mark them in the parent class with the open keyword, in addition to
marking the overriding method or parameter with the override keyword.
public is just encapsulation, it affects the visibility of classes/ methods. Public will make them visible everywhere.
Reference

What's the idiomatic way of inheriting data access functionality as well as object properties?

Suppose the following (slightly pseudo-code for brevity):
class Basic
{
String foo;
}
class SomeExtension extends Basic
{
String bar;
}
class OtherExtension extends Basic
{
String baz;
}
class BasicService
{
Basic getBasic()
{
}
}
class SomeExtensionService extends BasicService
{
SomeExtension getSomeExtension()
{
}
}
class OtherExtensionService extends BasicService
{
OtherExtension getOtherExtension()
{
}
}
What would be the most idiomatic, elegant way to implement the get-() service methods with the most possible code reuse?
Obviously you could do it like this:
class BasicService
{
Basic getBasic()
{
Basic basic = new Basic();
basic.setFoo("some kind of foo");
return basic;
}
}
class SomeExtensionService
{
SomeExtension getSomeExtension()
{
SomeExtension someExtension = new SomeExtension;
Basic basic = getBasic();
someExtension.setFoo(basic.getFoo());
someExtension.setBar("some kind of bar");
return someExtension;
}
}
But this would be ugly if Basic has a lot of properties, and also you only need one object, as SomeExtension already inherits Basic. However, BasicService can obviously not return a SomeExtension object.
You could also have the get methods not create the object themselves, but create it at the outermost level and pass it to the method for filling in the properties, but I find that too imperative.
(Please let me know if the question is confusingly formulated.)
EDIT: Okay, so it was. I'll try to explain it better. Say you have two model classes, A and B. You also have two classes for returning objects of class A and B (from a database for instance, with information scattered all over so any ORM doesn't apply). Now, say A and B contains a lot of overlapping information, so it makes sense to refactor into a superclass C and let A and B extend from it. However, the service classes are still particular to A and B and need to duplicate the code for reading the overlapping information. How could you refactor these into a service class C?
I would add constructor to A and B which accepts C and sets the fields accordingly. The advantage over your suggested solution is that your ExtensionServices don't have to know about basic fields.
It looks like you're setting default values to your Basic (and children) objects. It's probably best to do that in their constructors.
public class Basic
{
protected String foo;
// and other properties
public Basic()
{
foo = "some kind of foo";
// assign defaults to all other properties
}
}
public class SomeExtension extends Basic
{
protected string bar;
public SomeExtension()
{
super(); // set the default properties of the base class
bar = "some kind of bar";
}
}
Remember to call super() in the child constructors so that the inherited properties will also be assigned default values.
public class BasicService
{
public Basic getBasic()
{
return new Basic();
}
}
public class ExtensionService extends BasicService
{
#Override
public Basic getBasic()
{
return new SomeExtension();
}
}
At least with this structure, you eliminate having to instantiate two objects in ExtensionService, and you actually don't set default values in the service classes. Since SomeExtension is a child of Basic, you can return a SomeExtension at the end of a function whose declared return type is Basic.