I want to prevent Kotlin class method invocation as compilation error

Asked 2 years ago, Updated 2 years ago, 86 views

Since Kotlin does not want to invoke a specific method in only one of several implementation classes for an interface, we would like to prevent it from being used by making a compilation error.
Specifically, suppose you have the following interface and class definitions:

interfaceIHoge{
  fun test()
}
class A —IHoge
class B —IHoge
class C —IHoge

Suppose you do not want to invoke C.test() when and .In other words, if I write C.test() under this situation, I would like to make it a compilation error. Is there such a way?

Set the method to

funtest(){
  error()
}

It is easy to make runtime errors by doing something like that.However, is there any way to prevent C.test() from being called during compilation?An example of java is acceptable.

java kotlin

2022-09-30 21:49

2 Answers

Because you do not want to invoke C.test(), C should not implement IHoge in the first place.I will try to answer if I can or can't implement IHoge below.

1. If you can change the IHoge implementation

In this case, I think it is appropriate to separate the interfaces.

interfaceIHoge{
  fun test()
}

interface IFuga {
  // Non-test() methods in the original IHoge
}

class A —IHoge, IFuga
class B —IHoge, IFuga
class C —IFuga

2. If you cannot change the IHoge implementation

In this case, you may be asked to use the default implementation of the interface, so we define IPartial with a method other than test() and "merge" IHoge and IPartial in the new class D.
In addition, C does not inherit D directly, but deligate to avoid becoming a subclass of IHoge.

interfaceIHoge{
    fun f() = println("f()")
    fun test() = println("test()"
}

interface IPartial {
    funf();
}

open class D:IHoge,IPartial {
    override funf() = super<IHoge>.f();
}

class A —D()
class B —D()

class C(p:IPartial=D())—IPartial by p {
}

funmain(){
    val1 = mutableListOf<IHoge>(A(),B())
    // l1.add(C(A()))//<--- Compilation Error
    l1.forEach {it.test()}

    val2 = mutableListOf<IPartial>(A(), B(), C());
    l2.forEach {it.f()}
}
test()
test()
f( )
f( )
f( )


2022-09-30 21:49

It is different from the original usage, but Deprecated annotation is available.

level and DeprecationLevel.ERROR can result in compilation errors.

One caveat is that if you call the test() method via IHoge, you will not be able to detect it even if the actual instance is C.

interfaceIHoge{
    fun test()
}

class A:IHoge {
    override funtest(){}
}

class C:IHoge {
    @Deprecated(message="unavailable method", level=DeprecationLevel.ERROR)
    override funtest(){}
}

funmain(args:Array<String>){
    valc = C()
    c.test()// Compilation Error

    vali —IHoge=C()
    i.test()// No compilation errors
}

That's right.

However, as far as I can read the questionnaire, I feel that the design is wrong, just like other people's answers (so I think the design should be reviewed).


2022-09-30 21:49

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.