Search code examples
javakotlinbyte-buddy

How do I rebase existing class to remove certain interfaces that it implements


Folks, could you please advise how I can rebase existing class so that it doesn't have particular interface in its parents ?

For example

interface One {
  fun one(): Unit
}

interface Two {
 fun two(): Unit
}

class Test: One, Two {
  // implementation of one() and two()
}

val newClass = ByteBuddy()
    .rebase(Test::class.java)
    .name("com.test.Test2")
    .implement(Two::class.java)
    .make()
    .load(this.javaClass.classLoader, ClassLoadingStrategy.Default.WRAPPER)
    .loaded

val inst = newClass.declaredConstructors.first().newInstance()
val isOne = inst is One

Unfortunately isOne is still true. What am I missing ?


Solution

  • I've solved it through creating delegate class like this

    val fieldDelegate = "delegate"
    val unloaded = ByteBuddy()
        .subclass(Any::class.java)
        .defineField(fieldDelegate, Test::class.java, Opcodes.ACC_PRIVATE or Opcodes.ACC_FINAL)
        .name(Test::class.java.canonicalName + "Wrapper")
        .implement(Two::class.java)
        .defineConstructor(Visibility.PUBLIC)
        .withParameters(Test::class.java)
        .intercept(MethodCall.invoke(Object::class.java.getConstructor()).andThen(FieldAccessor.ofField(fieldDelegate).setsArgumentAt(0)))
        .method(ElementMatchers.isAbstract())
        .intercept(MethodDelegation.toField(fieldDelegate))
        .make()
    
    val clazz = unloaded
        .load(Test::class.java.classLoader, ClassLoadingStrategy.Default.WRAPPER)
        .loaded