expert
expert

Reputation: 30125

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 ?

Upvotes: 0

Views: 40

Answers (2)

expert
expert

Reputation: 30125

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

Upvotes: 0

Rafael Winterhalter
Rafael Winterhalter

Reputation: 44032

Byte Buddy does not really aim for removing properties. What you can do is to use ASM via the visit method, to remove elements from the byte code.

Or you can declare a new class, define it the way you and name it the same as the class you wanted to change.

Upvotes: 1

Related Questions