Я знаю, что мы можем передать класс в параметре, который имеет определенный класс в качестве супер. Например, см. это:
public void sampleMethod(Class<? super MyParentClass> class){
// my random code ?
}
и в котлине:
fun sampleMethod(class:Class<? super MyParentClass>){
// my random code ?
}
Но можно ли мне что-то вроде этого?:
public void sampleMethod(Class <? hasMethod myMethod> class){
// my random code ?
}
или в Котлине:
fun sampleMethod(class:Class<? hasMethod MyParentClass>){
// my random code ?
}
В основном я хочу принять класс только в том параметре, в котором есть метод, упомянутый в нем. Является ли это возможным?
Если да, то мне нужен код на java и Kotlin
Если нет, то подойдет любая альтернатива
Большинство ответов здесь не то, что я хочу. Итак, я объясняю это немного подробнее здесь:
public class MyClass1{
public static void main(String[] args){
doRandomTask(new ClassWhichHasMethod()); // works fine
doRandomTask(new ClassWhichDoesNotHaveMethod()); // gives error as it does not have that method
}
static class ClassWhichHasMethod{
public void theMethodIWant(){} // the method I want to check
}
static class ClassWhichDoesNotHaveMethod{ // no method here}
public static void doRandomTask(Class<? hasMethod theMethodIWant> class){
// my random code
}
}
То, что вы хотите, возможно нет без использования интерфейсов.
Хорошо @Оливье. Просто хотел узнать, возможно это или нет. Я не буду беспокоить тебя. Это никогда не было тем, чего я хотел в своем проекте. Просто любопытство.
Не могли бы вы поделиться кодом doRandomTask
, чтобы проще было понять проблему? Пример несколько сбивает с толку — doRandomTask(new ClassWhichHasMethod());
не скомпилируется, потому что doRandomTask
объявлен принимающим параметр типа Class<?>
, а ни ClassWhichHasMethod
, ни ClassWhichDoesNotHaveMethod
таковыми не являются.
Вы хотите передать экземпляр, описывающий класс, или вы хотите передать экземпляр класса, то есть объект?
Для этого вам нужно использовать интерфейс. Когда объект реализует интерфейс, это гарантирует, что он имеет методы, свойства и т. д., которые определяет интерфейс. Вам не нужно знать, что такое класс объект, просто его можно рассматривать как тип интерфейса:
interface MethodHaver {
fun myCoolMethod(something: String)
}
class Whatever : MethodHaver {
// need to implement/override the method in the interface to satisfy the contract
override fun myCoolMethod(something: String) {
// do a thing
}
}
class SomethingElse {
// uses anything that implements MethodHaver
fun doTheThing(myObject: MethodHaver) {
// the object definitely has this method, because the MethodHaver type requires it
myObject.myCoolMethod("wow")
}
}
Вы можете сделать это и с анонимными объектами, это не обязательно должны быть классы.
SomethingElse().doTheThing(object : MethodHaver {
override fun myCoolMethod(something: String) {
// do something
}
})
Или, в Kotlin, поскольку интерфейс имеет только один метод, вы можете сделать его функциональный интерфейс, а затем вместо этого вы можете передать лямбду, которая соответствует сигнатуре одного метода:
// note the 'fun' keyword before 'interface'
fun interface MethodHaver {
fun myCoolMethod(something: String)
}
// pass a lambda that matches the method signature, i.e. takes a String and returns Unit (doesn't return anything)
SomethingElse().doTheThing { something -> // do something }
И, наконец, в Kotlin вы можете пропустить интерфейсы и вместо них использовать типы функций.
class SomethingElse {
// accepts any function that takes a String and returns Unit
fun doTheThing(f: (String) -> Unit) {
// call the passed function like any other
f("wow")
}
}
// has the method you're interested in, but it isn't implementing an interface
class ClassWithMethod {
fun someMethod(string: String) {
println(string)
}
}
fun main() {
// call it passing a lambda
SomethingElse().doTheThing { println(it) }
// or pass a function reference, like a method on a specific object
val myClass = ClassWithMethod()
SomethingElse().doTheThing(myClass::someMethod)
}
В приведенном здесь примере ссылки на функцию вместо передачи объект, который имеет определенный метод вы можете просто передать ссылка на сам метод. Таким образом, вместо того, чтобы задействовать интерфейсы (чтобы система типов могла подтвердить, что вы передаете действительный объект с помощью соответствующего метода), вы можете исключить посредника и передать сам метод напрямую. Пока его подпись совпадает (параметры и тип возвращаемого значения), он действителен.
Так что да, много вариантов в зависимости от того, что именно вам нужно сделать!
Я отредактировал вопрос, чтобы было более понятно, чего я хочу.