How to use Cloneable?


#1

I must be doing something stupid :frowning: but

open class TempA : Cloneable {
    val s = "123"
    val i = 123
    val d = 1.23
}

class TempB : TempA() {
    val c = 'c'
}

Then in any func

    val tempb = TempB()
    val tempb2 = tempb.clone() as TempB

‘Cannot access clone: it is protected in TempB’ inline error appears in IDE.


Is the documentation correct?
#2

Plus it happens with just one class, no need for TempB


#3

clone is protected hence it will be subclass private in Kotlin. You will want to override the implementation as public so you can use it as you wish.

/**
 * Created by abubacker.siddik
 */
open class TempA : Cloneable {
    val s = "123"
    val i = 123
    val d = 1.23

    override public fun clone(): Any {
        return super.clone()
    }
}

#4

It seams clone can only used on the kotlin class which implement Cloneable.

what if I wanna use clone on a Cloneable java class as I can’t override clone() function in it.


#5

Can you provide a specific example?

Generally speaking clone in Java was a bad design and it’s not widely used. Kotlin has something similar: copy in data-classes. You should use it or similar approach if you have a choice.


#6

Some lib such as ‘OkHttp’ may suggest user use clone instead of create a new object.

In kotlin I can’t clone a OkHttpClient.


#7

I see why clone in Java was badly designed, since the interface defined no obvious contract, but I dont understand why the clone() method in Cloneable is protected. I want to have a method accept a Cloneable and then clone it, thats the whole point of a contract? Why make such a contract protected?


#8

Imagine that you have a class A which implements Cloneable with a custom function. Now you have class B inherit from class A without overriding the clone method. If you now try to clone object B you will not get a clone as only the members defined in A get cloned. The documentation states that:

The general intent is that, for any object x, the expression:
x.clone() != x
will be true, and that the expression:
x.clone().getClass() == x.getClass()
will be true, but these are not absolute requirements. While it is typically the case that:
x.clone().equals(x)
will be true, this is not an absolute requirement.

So the above problem would not violate this in the way I described. It would however return an object of the wrong type thereby not following rule number 2.
The way around this problem is to have class B also implement the Cloneable interface and override the clone method. (Also the documentation states, that clone should always call its super implementation)

As you and @vbezhenar said, not very well designed. Object copying/cloning is a complex subject. I have not yet seen any good implementation of it, which generalizes well to any type. That’s why Cloneable is so unintuitive IMO. Kotlin data classes can have a copy as they are much more heavily restricted and therefore copying is “simple”.