I have code (all of which I control) that looks like the following:
class FirstVeryLongName {
object ObjectA
object ObjectB
object ObjectC
}
class SecondVeryLongName {
object ObjectB
object ObjectD
}
The code I need to write is equivalent to
operation1(FirstVeryLongName.ObjectA, FirstVeryLongName.ObjectB)
operation2(SecondVeryLongName.ObjectB, SecondVeryLongName.ObjectD)
...except that the repeated uses of the very long names add a lot of clutter.
Here is something I hoped would work, but doesn't seem to:
FirstVeryLongName.run {
operation1(ObjectA, ObjectB)
}
...which I wasn't able to make work, even if I tried moving ObjectA and ObjectB into the companion of FirstVeryLongName and writing
FirstVeryLongName.Companion.run { ... }
...which I had hoped would give unqualified access to the objects, as it would have for a val in the companion object.
One thing I specifically want to avoid is typealiases or importing them as aliased names. I want it to be obvious without cross-references or manually looking at the imports where these are all coming from.
Is there some trick that would let me write this code and write FirstVeryLongName, ObjectA, and ObjectB each exactly once?
It makes sense to me that it isn't working the way you tried it.
The class name itself is no instance and run or with therefore doesn't apply. It's the same as just writing the package name and nothing else. This doesn't work either.
Regarding the Companion-approach, I assume you implemented the following:
class FirstVeryLongName {
companion object {
object ObjectA
object ObjectB
object ObjectC
}
}
and a usage such as:
with(FirstVeryLongName.Companion) {
operation1(ObjectA, ObjectB)
}
Actually this could work as long as you have such properties defined for the companion (this applies to functions as well). Actually that is also something you mentioned yourself. You may want to look at the generated byte code to see what an object actually corresponds to, if you didn't do it already. If you did, you can skip the rest of this paragraph ;-) Think of it as if it were just nested classes. In the example above we therefore have 3 nested classes inside the Companion-class, which is inside the FirstVeryLongName-class.
From Kotlin the access to the singleton INSTANCE-field is hidden from you. In the Kotlin code FirstVeryLongName.Companion.ObjectA can represent both, the type and the singleton instance reference. The context is relevant.
As you can't use class-names-only or part of an import-statement in run/with, you can't also simplify the access to the singleton instance in this way.
You can however do something as follows. Note: I clearly do not recommend this approach as is (I do not believe that you really need both: the object and the val). Maybe you can also use an object expression there? There is most probably an easier way to structure your code, but without appropriate context I can only guess... I may be wrong):
class FirstVeryLongName {
companion object {
val ObjectA = FirstVeryLongName.ObjectA // can you use an object expression here?
val ObjectB = FirstVeryLongName.ObjectA
val ObjectC = FirstVeryLongName.ObjectA
}
object ObjectA
object ObjectB
object ObjectC
}
Now the run/with works as you desire, but now it actually accesses the val-reference which points to the object:
with(FirstVeryLongName.Companion) {
operation1(ObjectA, ObjectB)
}
Just showing a simple example using an object expression. You may either want to have a common superclass, interface or, if you do not mind, you can even use object : Any() here:
class FirstVeryLongName {
companion object {
val ObjectA = object : interfaces.ObjectA { /* ... */ }
// ...
}
}
Usage still looks the same. Now only the signature of operation1 may differ.
Related
sealed class Genre{
sealed class Fiction : Genre(){
object Classics: Fiction()
object Fantasy: Fiction()
object ScienceFiction: Fiction()
}
sealed class NonFiction: Genre(){
object Biography: NonFiction()
object Business: NonFiction()
object Feminism: NonFiction()
object Politics: NonFiction()
object SelfHelp: NonFiction()
}
override fun toString(): String {
return this::javaClass.get().simpleName
}
I do not understand this context return this::javaClass...
When I press ctrl and hover over "this" it points to Genre class, This is confusing me.
I believe someone made a mistake in this code, making it a little confusing. What he/she really meant was:
this.javaClass.simpleName
Let's analyze it step by step:
this.javaClass creates Class object for provided this object. It could return e.g. Class<Fantasy>.
this::javaClass creates a property accessor for javaClass property of this object. It can be used later to access javaClass of this.
get() is called on property accessor to get the javaClass of this.
This way get() returned e.g. Class<Fantasy> and simpleName returned the name of a class.
I'm not sure if this explanation is at all possible to understand. But what is important is that this::javaClass.get() is the same as simply this.javaClass, probably done by a mistake.
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.
I am currently learning D and struggling to understand how operator overloading could work for a class? Overriding opCmp makes sense and works correctly for a struct, but for a class it requires taking the right hand side as a Object instead of as my type.
This means I can't access any members to do a comparison. What's the point in the overload then? Am I missing something?
Sure you can access your members:
class MyClass {
int member;
override int opCmp(Object other) {
if (auto mcOther = cast(MyClass)other) {
// other, and thus mcOther, is an instance of MyClass.
// So we can access its members normally:
return member < mcOther.member ? -1
: member > mcOther.member ? 1
: 0;
} else {
// other is not a MyClass, so we give up:
assert(0, "Can't compare MyClass with just anything!");
}
}
}
The reason opCmp for classes takes Object as a parameter is it's being introduced in the Object class, from which every D class derives. Introducing opCmp there was a sensible choice back in the day, but less so now. However, since we don't want to break every piece of D code out there that uses opCmp (and opEquals, toHash and toString) with classes, we're kinda stuck with that choice.
In object-oriented and functional programming, an immutable object is
an object whose state cannot be modified after it is created. This is
in contrast to a mutable object, which can be modified after it is
created.
Mutable or Immutable class below? I think it's mutable because static field singleton changes after new MavenPush(project), but I need 100% correct answer. It's groovy code, but it's like Java code
final class MavenPush {
private static volatile MavenPush singleton = null
private final def project
private MavenPush(project) {
this.project = project
}
static MavenPush with(project) {
if (singleton == null) {
synchronized (MavenPush.class) {
if (singleton == null) {
singleton = new MavenPush(project)
}
}
}
return singleton
}
}
An instance of the class is immutable, the class is mutable as a field of the class gets mutated.
This is an immutable instance; but also useless - there are no getters (unless groovy does that implicitly - I am not aware if this happens).
As stated already, the instances of the class look immutable (final properties can only be initialized in the c'tor). But since you left the type out for project this really depends on that. If you pass a String you really have something immutable (Java strings are immutable) - if not: this is basically just an immutable reference to something mutable and all your expectiations about that may shatter at some point.
Now for that static member:
From an OO view, singleton seems like the wrong name. The singleton pattern is quite well known, but what you have here, is a "last item changed cache".
From an FP view: with is often used in a context, where you want to create a modified version of immutable data. So if you run with from instances you earlier got, you dont "copy and change" from the instance but from your "global last item cache (singleton)" - that is no problem with the simple example (just one property), but might be with the "real 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