Возьмите класс в качестве параметра, в котором есть определенный метод

Я знаю, что мы можем передать класс в параметре, который имеет определенный класс в качестве супер. Например, см. это:

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 
   }

}

Я отредактировал вопрос, чтобы было более понятно, чего я хочу.

Sambhav. K 07.05.2022 11:37

То, что вы хотите, возможно нет без использования интерфейсов.

Olivier 07.05.2022 11:39

Хорошо @Оливье. Просто хотел узнать, возможно это или нет. Я не буду беспокоить тебя. Это никогда не было тем, чего я хотел в своем проекте. Просто любопытство.

Sambhav. K 07.05.2022 11:41

Не могли бы вы поделиться кодом doRandomTask, чтобы проще было понять проблему? Пример несколько сбивает с толку — doRandomTask(new ClassWhichHasMethod()); не скомпилируется, потому что doRandomTask объявлен принимающим параметр типа Class<?>, а ни ClassWhichHasMethod, ни ClassWhichDoesNotHaveMethod таковыми не являются.

Chaosfire 07.05.2022 12:47

Вы хотите передать экземпляр, описывающий класс, или вы хотите передать экземпляр класса, то есть объект?

knittl 07.05.2022 15:19
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
5
78
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Для этого вам нужно использовать интерфейс. Когда объект реализует интерфейс, это гарантирует, что он имеет методы, свойства и т. д., которые определяет интерфейс. Вам не нужно знать, что такое класс объект, просто его можно рассматривать как тип интерфейса:

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

В приведенном здесь примере ссылки на функцию вместо передачи объект, который имеет определенный метод вы можете просто передать ссылка на сам метод. Таким образом, вместо того, чтобы задействовать интерфейсы (чтобы система типов могла подтвердить, что вы передаете действительный объект с помощью соответствующего метода), вы можете исключить посредника и передать сам метод напрямую. Пока его подпись совпадает (параметры и тип возвращаемого значения), он действителен.

Так что да, много вариантов в зависимости от того, что именно вам нужно сделать!

Другие вопросы по теме

Как я могу исправить эту ошибку, которая иногда возникает при запуске моего кода?
Dart: объект выдает результат только один раз, даже при многократном вызове
Phaser 3: вызов функции из другого класса
Получение ошибки: «ошибка: статическое утверждение не удалось: тип результата должен быть конструируемым из типа значения входного диапазона» при построении векторов классов
Не удается получить, если использовать переменную объекта в качестве параметра
Есть ли способ встроить элемент класса в элемент класса в Entity Framework?
Ошибка класса Python ClassMethod: принимает ровно 1 аргумент (даны 2)
Python: ООП, учебник 1: Классы и экземпляры: как использовать себя?
Python не может вывести статический тип подкласса при использовании фабрики обработчиков
Почему код внутри класса выполняется при его определении, а код внутри функции не выполняется до тех пор, пока он не будет вызван?