Super constructor cannot be passed a self reference unless parameter is declared by-name - oop

Well, I have something like this:
trait A
class Serving(a: => A)
object App extends Serving(App.Main) {
object Main extends A
}
And I get the error super constructor cannot be passed a self reference unless parameter is declared by-name. I can work around by doing
object App extends Serving(Serv.Main)
object Serv {
object Main extends A
}
but I don't want to. It adds 2 extra .classes and it strikes me as unelegant.
And using object App extends Serving(this.Main) also creates an error. The structure of A and Serving cannot really be changed, but is there any way to work around this error?

Your code compiles just fine in Scala 2.8.1, even if the parameter is not declared by-name.

Related

What's an example of using an overridden property in the Base Class initialization (either directly or indirectly)?

It means that, by the time of the base class constructor execution, the properties declared or overridden in the derived class are not yet initialized. If any of those properties are used in the base class initialization logic (either directly or indirectly, through another overridden open member implementation), it may lead to incorrect behavior or a runtime failure. When designing a base class, you should therefore avoid using open members in the constructors, property initializers, and init blocks.
I was studying Inheritence from Kotlin docs, and I got stuck here. There was another post which asked a question about this, but the answers were just what the docs said in a different way.
To be clear, I understood the data flow between constructors and inheritence. What I couldn't understand was how we can use an overridden property in a base class initialization. It says
It could happen directly or indirectly
  What does this actually mean? How can the base class can somehow access to the overridden property in the derived class?
Also, it said
You should therefore avoid using open members in the constructors,
property initializers and init blocks.
 So how can we properly use open properties?
EDIT FOR THE COMMENT:
fun main ()
{
val d = Derived("Test2")
}
open class Base()
{
open val something:String = "Test1"
init
{
println(something) //prints null
}
}
class Derived(override val something: String): Base()
What does this actually mean? How can the base class can somehow access to the overridden property in the derived class?
This is one direct way:
abstract class Base {
abstract val something: String
init {
println(something)
}
}
class Child(override val something: String): Base()
fun main() {
Child("Test") // prints null! because the property is not initialized yet
}
This prints null, which is pretty bad for a non-nullable String property.
You should therefore avoid using open members in the constructors, property initializers and init blocks.
So how can we properly use open properties?
You can use these properties in regular methods on the base class (or in custom property getters):
abstract class Base {
abstract val something: String
fun printSomething() {
println(something)
}
}
class Child(override val something: String): Base()
fun main() {
Child("Test").printSomething() // correctly prints "Test"
}
EDIT: Here are some clarifications regarding the follow-up questions in the comments.
I couldn't quite get why the code in the init block went for the parameter in the child class constructor
I think you might be confused by Kotlin's compact syntax for the primary constructors in general, which probably makes the debugger's flow hard to understand. In the Child declaration, we actually declare many things:
the argument something passed to the Child's primary constructor
the property something on the Child class, which overrides the parent's one
the call to the parent constructor (Base())
When Child() is called, it immediately calls the Base() no-arg constructor, which runs the init block.
We didn't even delegate the base constructor with a parameter or anything, but it still went for the parameter who did the overriding
You might be mixing declarations and runtime here. Although we declare things in the Base class and in the Child class, there is only 1 instance at runtime (an instance of Child) in this example code.
So, in fact, there is only 1 property called something here (only one place in memory). If the init block accesses this property, it can only be the property of the child instance. We don't need to pass anything to the Base constructor because the init block is effectively executed with the data/fields of the Child instance.
Maybe you would be less confused if you saw the Java equivalent of this. It's obvious if you think of the abstract something as a declaration of a getter getSomething(). The child class overrides this getSomething() method and declares a private something field, the getter returns the current value of the field something. But that field is only initialized after the constructor of the parent (and the init block) finished executing.

How is Companion different from INSTANCE

How are an object INSTANCE and a Companion object different and which situations should they be used in.
ObjectName.INSTANCE.iAmStaticMethod();
ClassName.Companion.iAmStaticMethod();
ClassName.Companion can be used also for accessing a non static method
iAmStaicMethod() is a static function and iAmNonStaticMethod() is a non-static function.
So, to call the above methods in Java, write the below code:
ClassName.iAmStaticMethod(); // works fine
ClassName.iAmNonStaticMethod(); // error: not a static method
ClassName.Companion.iAmStaticMethod(); // instance method remains
ClassName.Companion.iAmNonStaticMethod(); // the only way it works

Using public and private methods inside their class in Perl 6

If I have a public method, I can call it inside its class using both $.name and self.name:
class TEST {
has Int $.a;
method b($x) {
return $!a * $x;
}
method c($y) {
return self.b($y) * 3; # or $.b($y)
}
}
my $m = TEST.new(a => 10);
say $m.c(2); # 60
But if I make b a private method, I only can call it with self!b, not $!b, otherwise I get the following error message:
Attribute $!b not declared in class TEST
What's behind this rule? What are the rules of calling a method inside its own class?
An attribute can always be referred to as $!foo in a class. If you do that, than the code will be generated to directly access the attribute itself, and any classes subclassing your class will not be able to change this behaviour.
If you use has $.foo in the declaration of a class, it means that a public accessor (and if you add is rw it can also function as a mutator).
When you use $.foo in your code otherwise, it is exactly the same as $( self.foo ). This means that it will call the method foo on self, and itemize the return value (make it a single "thing" if it wasn't yet). This will go wrong if you defined your attribute with $!foo and you did not supply a method foo yourself.
This goes even further: $.bar really means self.bar: you only need to have a method existing by the name bar, which may not be related to any attribute at all.
If you define a private method !baz, the ! just indicates the privacy of the method, which means you need to call it indeed as self!baz. There is no short syntax for it.
Personally I dislike the fact that you can say $.zippo even if zippo is not an attribute. But I'm afraid that ship has sailed. But this behaviour is now causing you confusion :-(
So what's behind the rule for not having a short syntax for calling a private method? Not sure, I guess really that $!foo was already taken to mean direct access to the attribute, and provide you with a compile time error if the attribute doesn't exist.
Hope this answers your question!

'this' is not defined in this context

How can I solve the following case?
interface I
class A(i: I)
class C : I, A(this) // << --- 'this' is not defined in this context
In short, I want to pass the class instance to super class constructor.
Is it possible in Kotlin?
P.S.
All the answers are good and technically correct. But let's give a concrete example:
interface Pilot {
fun informAboutObstacle()
}
abstract class Car(private val pilot: Pilot) {
fun drive() {
while (true) {
// ....
if (haveObstacleDetected()) {
pilot.informAboutObstacle()
}
// ....
}
}
fun break() {
// stop the car
}
}
class AutopilotCar : Pilot, Car(this) { // For example, Tesla :)
override fun informAboutObstacle() {
break() // stop the car
}
}
This example don't look too contrived, and why can't I implement it with OOP-friendly language?
No, this is not possible on the JVM. this is only available after the super class has been initialized.
From
https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.10.2.4
The instance initialization method (§2.9.1) for class myClass sees the new uninitialized object as its this argument in local variable 0. Before that method invokes another instance initialization method of myClass or its direct superclass on this, the only operation the method can perform on this is assigning fields declared within myClass.
So the bytecode instruction aload 0 to push this on the stack is forbidden before the super-class constructor is called. That's why it cannot be passed as an argument to the super-constructor.
Kotlin was born as a JVM language and aims for maximum interoperability with Java code and a minimum overhead of its language features. While Kotlin could have chosen to orchestrate object initialization in a different way, it would create problems in mixed Java-Kotlin class hierarchies and add significant overhead.
In the good tradition of OOP languages such as Java, C# or Swift, Kotlin doesn't allow you to leak the this reference before the call to superclass initialization has completed. In your special case you're just storing the reference, but in just a slightly different case the superclass code might try to use the received object, which at that point is still uninitialized.
As a specific example of why languages don't allow this, consider a case where A is a class from a library you use and this rule is not in effect. You pass this like you do and things work fine. Later you update the library to a newer version and it happens to add something as benign as i.toString() to its constructor. It has no idea it's actually calling an overridden method on itself. Your toString() implementation observes all its invariants broken, such as uninitialized vals.
This design suffers from other problems, not just the circular initialization dependency you are struggling with now. In a nutshell, the class A expects this:
But instead you create this:
The class A has a dependency on a collaborator object of type I. It doesn't expect itself as the collaborator. This may bring about all kinds of weird bugs. For example your C.toString() may delegate to super.toString() and A.toString() (A is the super of C) may call into I.toString(), resulting in a StackOverflowError.
I can't say from your question whether A is designed for extension, which would make the C : A part correct, but you should definitely disentangle A from I.

Swift class properties not initialized when constructed by Objective C code

I'm attempting to create a class in Swift 3 to implement a Cordova plugin. I have this building and running, but the application crashes whenever any properties of the class are accessed. I've tried two ways of initializing the class:
#objc(DSFMediaCentre)
class DSFMediaCentre : CDVPlugin
{
var players = [UUID:DSFPlayerHandler] ();
...
}
and
#objc(DSFMediaCentre)
class DSFMediaCentre : CDVPlugin
{
var players :[UUID:DSFPlayerHandler];
override init () {
players = [:];
}
...
}
However, when my players property is used, the result is a EXC_BAD_ACCESS exception, with an address that looks like a null pointer dereference.
The object is being created by Objective C code, which is a language I have no familiarity with at all, but I think this is the line that creates it:
obj = [[NSClassFromString(className)alloc] initWithWebViewEngine:_webViewEngine];
The CDVPlugin class contains a comment stating that initWithWebViewEngine should not be overridden (and indeed I do not seem to be able to override this method, because while it is declared in the CDVPlugin.m file, it isn't mentioned in CDVPlugin.h, so the Swift compiler doesn't seem to know about it), but rather initialization code should be placed in a method called pluginInitialize instead. However, if I do that I get a compiler error ("Class DSFMediaCentre has no initializers").
Furthermore, if I put my init() method back in and set it to call pluginInitialize(), like this:
override init () {
super.init(); // necessary otherwise next line is an error
pluginInitialize();
}
override func pluginInitialize() {
players = [:];
}
the error then changes to "Property 'self.players' not initialized at super.init call".
How do I make this class initialize correctly?
You have a mismatch between the strict initialization system required by the language and the procedure used by the framework you're working with.
Swift demands that a) properties be initialized as part of object construction, and b) that construction be chained to the type's supertype. But the CDVPlugin type is doing the construction on your behalf; you don't have the ability to customize it. (This makes more sense in ObjC, because it doesn't have the same compile-time restrictions as Swift.)
The situation is similar to unpacking an object from a nib file. In that case too, because it's the nib loading system that's constructing your object, you don't have the ability to customize the initializer. Your type will always be constructed by init(coder:). In a certain sense, your initialization point moves further down, to awakeFromNib(), and among other things, that forces outlets to other objects in the archive to be declared as optional, usually implicitly unwrapped.
The same solution should avail you here. You should consider pluginInitialize() to be your initialization point. The language then requires that properties be optional, since they are not filled at its initialization point. Therefore, make the property an IUO:
#objc(DSFMediaCentre)
class DSFMediaCentre : CDVPlugin
{
var players :[UUID:DSFPlayerHandler]!
override func pluginInitialize() {
players = [:];
}
}
and all should be well.
The other solution is to use lazy keyword
lazy var players :[UUID:DSFPlayerHandler] = [:]
So, you don't need to initialize players in initializer but still make sure players always non-nulable