How to use Cloneable?

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.

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

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()
    }
}

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.

1 Like

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.

Some lib such as ā€˜OkHttpā€™ may suggest user use clone instead of create a new object.

In kotlin I canā€™t clone a OkHttpClient.

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?

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ā€.