Разве Func не <T, bool> и Предикат <T> то же самое после компиляции?

Котлин считает свойство неинициализированным до конца его инициализатора, поэтому он не может использоваться внутри собственного инициализатора даже в лямбдах. Эта семантика аналогична ограничению использования локальной переменной внутри ее инициализатора .

Существует несколько способов:

  • Используйте выражение object , которое позволяет ссылаться на this объявленного объекта:
    private var runnable: Runnable = object : Runnable {
        override fun run() {
            /* Do something very important */
            handler.postDelayed(this, 5000)
        }
    }
    
    Это хорошо работает
  • Используйте lateinit var или делегированное свойство с Delegates.notNull(). ] :
    private lateinit var runnable: Runnable
    init {
        runnable = Runnable { 
            /* Do something very important */
            handler.postDelayed(runnable, 5000)
        }
    }
    
    Тот же инициализатор будет работать с этим объявлением:
    private var runnable: Runnable by Delegates.notNull()
    
  • Внедрить и использовать саморегуляцию для инициализаторов самостоятельно:
    class SelfReference(val initializer: SelfReference.() -> T) {
        val self: T by lazy {
            inner ?: throw IllegalStateException("Do not use `self` until initialized.")
        }
    
        private val inner = initializer()
    }
    
    fun  selfReference(initializer: SelfReference.() -> T): T {
        return SelfReference(initializer).self
    }
    
    И тогда вы можете написать что-то вроде
    private var runnable: Runnable = selfReference { 
        Runnable {
            /* Do something very important */
            handler.postDelayed(self, 5000)
        } 
    }
    

21
задан abatishchev 18 April 2012 в 13:52
поделиться

4 ответа

Они совместно используют ту же подпись, но они - все еще различные типы.

18
ответ дан 29 November 2019 в 20:51
поделиться

Роберт С. совершенно прав; например: -

class A {
  static void Main() {
    Func<int, bool> func = i => i > 100;
    Predicate<int> pred = i => i > 100;

    Test<int>(pred, 150);
    Test<int>(func, 150); // Error
  }

  static void Test<T>(Predicate<T> pred, T val) {
    Console.WriteLine(pred(val) ? "true" : "false");
  }
}
17
ответ дан 29 November 2019 в 20:51
поделиться

Даже без обобщений вы можете иметь разные типы делегатов, которые идентичны в сигнатурах и типах возвращаемых данных. Например:

namespace N
{
  // Represents a method that takes in a string and checks to see
  // if this string has some predicate (i.e. meets some criteria)
  // or not.
  internal delegate bool StringPredicate(string stringToTest);

  // Represents a method that takes in a string representing a
  // yes/no or true/false value and returns the boolean value which
  // corresponds to this string
  internal delegate bool BooleanParser(string stringToConvert);
}

В приведенном выше примере два неуниверсальных типа имеют одинаковую сигнатуру и возвращаемый тип. (И на самом деле также, как Predicate<string> и Func<string, bool>). Но, как я пытался указать, «значение» двух разных.

Это похоже на то, что если я сделаю два класса, class Car { string Color; decimal Price; } и class Person { string FullName; decimal BodyMassIndex; }, то просто потому, что оба они содержат string и decimal, это не значит, что они «одинаковые» тип.

0
ответ дан 29 November 2019 в 20:51
поделиться

Более гибкое семейство Func появилось только в .NET 3.5, поэтому оно будет функционально дублировать типы, которые должны были быть включены ранее по необходимости.

(Плюс name Предикат сообщает предполагаемое использование читателям исходного кода)

2
ответ дан 29 November 2019 в 20:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: