How can i override the method (of behavior):
compile: code notifying: requestor trailer: bytes ifFail: failBlock
in the new function (that overrides compile of Behavior) I need to compile the method in the object "code". Do I need to declare it as a class method?
and also, is code (which contains the method to be compiled) a String type?
What is confusing is that the browser does not show the parallel class-side hierarchy...
You know that true is an instance of class True, so if you send a message to true, it must be understood by it's class True, or one of its superclasses. We can use a browser for browsing that set of messages:
True browseHierarchy.
If we inquire the inheritance by repeatedly sending superclass messages, that closely matches what the hierarchy browser shows, so far so good :
True superclass -> Boolean.
Boolean superclass -> Object.
Object superclass -> ProtoObject.
ProtoObject superclass -> nil.
Now what if you send a message to the class True itself? It will be understood by it's class, True class (which is a metaclass True class class == Metaclass).
But let's inquire the hierarchy of the metaclass True class :
True class superclass -> Boolean class.
Boolean class superclass -> Object class.
Object class superclass -> ProtoObject class.
ProtoObject class superclass -> Class.
Class superclass -> ClassDescription.
ClassDescription superclass -> Behavior.
Behavior superclass -> Object.
Object superclass -> ProtoObject.
ProtoObject superclass -> nil.
Ah Ah! It's deeper than what the browser shows...
Unsurprisingly, you find Class in this hierarchy, so as to satisfy this:
"True is a (kind of) class" (True isKindOf: Class) -> true.
Since True class inherits from Behavior, any method of Behavior is understood by all the instances of True class (normally, there is a single one, True class soleInstance == True).
So, back to the problem, when you want to add an instance-side method to true, you ask to its class to compile a new method:
True compile: 'asInt ^1'.
Now, true responds to this #asInt message:
(true respondsTo: #asInt) -> true.
You can then send to any instance of True (again, there should be a single one, True initializedInstance == true):
true asInt -> 1.
If you want to install a method at class side, that the class True responds to, then you ask to the metaclass, True class, or one of it's superclass:
Boolean class compile: 'soleInstance ^self initializedInstance'.
Now you can ask:
True soleInstance -> true.
The lesson is this one: if some tool (like the browser) is just showing a partial view of what an object is, responds to, inherits from, etc..., then try using another tool like:
True class explore.
And a more important lesson: you're in a live environment, so ultimately use the swiss knife tool - send a message, if it is not understood, some object will kindly tell you ;)
Now since I've mostly solved your homework, here is a harder problem for you: if you wanted to intercept the compilation of a method compiled at class side, where would you override #compile:...?
If you want to know whether you should define it on the class side, why don't you try it and report back to us ;) That is the magic of a live, dymanic system - it's yours to experiment in!
Code is a string type - normally ByteString
Related
I have the following base class and interface
open class Base {
open fun foo() { println("Base.foo") }
}
fun interface Delegate {
fun foo(): Unit
}
Now I want to override the foo method of a subclass Composed of Base using delegation, like this:
class Composed(delegate: Delegate) : Base(), Delegate by delegate
This works as I intend. Instances of Composed use the foo method of delegate, instead of the one from Base. But, I get a warning from IntelliJ:
Delegated member 'fun foo(): Unit' hides supertype override: public open fun foo(): Unit defined in Base. Please specify proper override explicitly.
Why do I get this error? What is "bad" about implicitly overriding the foo method? Are there any drawbacks I don't see? Specifying the override explicitly seems like a lot of unnecessary code, especially if I do this for multiple methods and multiple subclasses.
I think there's a warning for at least two reasons:
The behavior is ambiguous about which foo() implementation is used. There's no intuitive expectation about which foo() should win, since the superclass and the delegate are declared on the same line. I've been using Kotlin for a few years, and I couldn't have told you which behavior to expect without testing it, because this is kind of an unusual setup.
You will get possibly unexpected behavior if any of the functions in the Base superclass call foo(), because they will be calling the delegate's foo() instead of their own. It might be OK in this case, but in most cases, when you override a function, you want to call super in case there are necessary side-effects. That's not possible with the delegate.
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.
I am learning Kotlin programming language perfectly. I try to write code in different patterns and try to understand. However, I did not understand the thing. Can you help me, please?
Here it is:
open class Parent {
open val foo = 1
init {
println(foo)
}
}
class Child: Parent() {
override val foo =2
}
fun main() {
Child()
}
In this code, 0 is the output. How will this be?
This is about the order of construction — and is a subtle gotcha that's easy to fall prey to. (I'm afraid this answer is a bit long, but the issues here are well worth understanding.)
There are a few basic principles colliding here:
Superclass initialisation happens before subclass initialisation. This includes code in constructors, code in init blocks, and property initialisers: all of that happens for a superclass before any in a subclass.
A Kotlin property consists of a getter method, a setter method (if it's a var), and a backing field (if needed). This is why you can override properties; it means that the accessor method(s) are overridden.
All fields initially hold 0/false/null before they get initialised to any other value. (Normally, you wouldn't get to see that, but this is one of those rare cases. This differs from languages like C where if you don't explicitly initialise a field it can hold random values depending on what that memory was previously used for.)
From the first principle, when you call the Child() constructor, it will start off by calling the Parent() constructor. That will set the superclass's foo field to 1, and then get the foo property and print it out. After that, the Child initialisation happens, which in this case is simply setting its foo field to 2.
The gotcha here is that you effectively have two foos!
Parent defines a property called foo, and that gets accessor methods and a backing field. But Child defines its own property called foo, overriding the one in Parent — that one overrides the accessor methods, and gets its own backing field as well.
Because of that override, when the Parent's init block refers to foo, it calls the getter method which Child overrides, to get the value of Child's backing field. And that field hasn't been initialised yet! So, as mentioned above, it's still holding its initial value of 0, which is the value that the Child getter returns, and hence the value that Parent constructor prints out.
So the real problem here is that you're accessing the subclass field before it's been initialised. This question shows why that's a really bad idea! As a general rule:
A constructor/initialiser should never access a method or property that could be overridden by a subclass.
And the IDE helps you out here: if you put your code into IntelliJ, you'll see that the usage of foo is marked with the warning ‘Accessing non-final property foo in constructor’. That's telling you that this sort of problem is possible.
Of course, there are more subtle cases that an IDE might not be able to warn you about, such as if a constructor calls a non-open method that calls an open one. So care is needed.
There are occasions when you might need to break that rule — but they're very rare, and you should check very carefully that nothing can go wrong (even if someone comes along later and creates a new subclass). And you should make it very clear in comments/documentation what's going on and why it's needed.
Now, let's with java understand why. In Java, it's impossible to override fields and under the hood in Kotlin is the same. When you override a property, in fact, you override a getter, not a field. For instance, you can override a property that doesn't have a field with a property that has a field. That's totally legal. However, when both a property from a superclass and an overridden property in a subclass have fields, that might lead to unexpected results. Let's see what bytecode is generated for the Kotlin class in my example. As usual, I'll look at the corresponding Java code instead for simplicity.
public class Parent {
private final int foo = 1;
public int getFoo() {return foo;}
public Parent(){
System.out.println(getFoo());
}
}
public final class Child extends Parent {
private final int foo = 2;
public int getFoo() {return foo;}
}
public class Main
{
public static void main (String[] args) {
new Child();
}
}
Note two things here. First, the foo get to is trivial, so a field and a getter correspond to the full property. Then because the property is open and can be overridden in a subclass, its usage inside the class is compiled to a getter code, not a field code. Now, the generated code for the child class. Note that the overridden property in the parent class is also compiled to a field and a getter, and now it's another field. What happens when you create an instance of the child class? At first at the parent constructor is called, the parent constructor initializes the first fulfilled with one. But inside the init section, an overridden getter is called which calls get foo from the child class. Because the field in the child class is not yet initialized, 0 is returned. That's why 0 is printed here.
Please go through following points:
Initializer Blocks i.e. init {} block are called during an instance initialization. They are called after Primary Constructor.
In above code println(foo) is placed inside init block.
Hence, the value which gets printed i.e. 0 in this case, is the value before assignment statement open val foo = 1.
If you want the output to be 1 then make following changes:
open class Parent {
open var foo : Int = 0
init {
foo = 1
println(foo)
}
}
class Child: Parent() {
override var foo =2
}
fun main() {
Child()
}
And lastly, please go through this post. This will help you in getting better understanding of this area.
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.
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