Как расширить класс класса Kotlin или использовать общие для создания простого свойства getter, который будет работать во всех подклассах Number?

Я пытаюсь узнать больше о расширениях и дженериках абстрактного класса Kotlin, создав очень простые методы и свойства getters, которые расширяют встроенные классы. Я в основном был успешным, но меня превзошел класс Number. Мое свойство test Number.sgn предназначено для возврата знака (1 или -1 как Int) любого подкласса Number. Для простоты отрицательные должны возвращать -1, а положительные числа и 0 должны возвращаться 1. Я не особо интересуюсь прецедентом этого метода, но для понимания того, как писать что-то простое – и почему мой код генерирует ошибка. Единственный импорт в моем модуле – kotlin.text.* И сообщение об ошибке, которое я получаю, ссылается на конфликт там. Я просто не понимаю, почему он конфликтует и как его преодолевать, хотя я предполагаю, что это новичок.

Сначала я написал код для расширения класса Int, который отлично работает:

inline val Int.sgn get() = if (this<0) -1 else 1 // sign of number

Затем я попытался обобщить и перенести его в класс Number, например:

inline val Number.sgn get() = if (this<0) -1 else 1 // doesn't compile

и ошибка компиляции выглядит следующим образом:

unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public fun String.compareTo(other: String, ignoreCase: Boolean = ...): Int defined in kotlin.text inline fun Number.sgn() = if (this<0) -1 else 1 ^

Затем я попробовал другой подход, используя дженерики:

inline val <T:Number> T.sgn get() = if (this<0) -1 else 1

и я получил ту же ошибку от компилятора:

error: unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public fun String.compareTo(other: String, ignoreCase: Boolean = ...): Int defined in kotlin.text inline val <T:Number> T.sgn get() = if (this<0) -1 else 1 ^

Может ли кто-нибудь помочь мне понять, почему существует несоответствие типа, и почему здесь имеет значение kotlin.text ? Есть ли подход, который я мог бы использовать для преодоления этой проблемы и получить этот атрибут getter для всех подклассов Number? (Опять же, я знаю, что это не значимый вариант использования, а упрощенный пример, чтобы помочь мне понять принципы, лежащие в основе этого.) Спасибо заранее за любые советы, которые каждый может дать …

Ваша первая функция работает, потому что Int реализует Comparable<Int> , это то, на что переводется оператор < . Однако, если вы посмотрите на класс Number , вы увидите, что он имеет в нем только функции для конверсий по своим различным подклассам – он не реализует Comparable , поэтому вы не можете использовать оператор < на нем.

Вместо этого вы можете сначала преобразовать свой Number в Double , а затем посмотреть, является ли он отрицательным:

 inline val <T : Number> T.sgn get() = if (this.toDouble() < 0) -1 else 1 

Вы также можете сделать свой исходный код (с или без дженериков), compareTo функцию compareTo для Number в качестве расширения:

 operator fun Number.compareTo(other: Number) = this.toDouble().compareTo(other.toDouble()) 

Просто имейте в виду, что отбрасывание всего на Double может привести к потере точности.