Kotlin 扩展函数是否可以始终转换为成员?
我有一些扩展函数,我想转到成员函数。但我不知道如何做到这一点,特别是对于嵌套泛型类型链Kotlin 扩展函数是否可以始终转换为成员?,kotlin,Kotlin,我有一些扩展函数,我想转到成员函数。但我不知道如何做到这一点,特别是对于嵌套泛型类型链 import Y.* abstract class File<T> open class Y private constructor() { open class localhost_ { @JvmName("usr") operator fun div(a: usr.Companion) = usr<localhost_>() @JvmName("bin")
import Y.*
abstract class File<T>
open class Y private constructor() {
open class localhost_ {
@JvmName("usr") operator fun div(a: usr.Companion) = usr<localhost_>()
@JvmName("bin") operator fun div(a: bin.Companion) = bin<localhost_>()
@JvmName("etc") operator fun div(a: etc.Companion) = etc<localhost_>()
companion object: localhost_()
}
open class bin<T>: File<T>() { companion object }
open class sh<T>: File<T>() { companion object }
open class etc<T>: File<T>() { companion object }
open class vim<T>: File<T>() { companion object }
open class usr<T>: File<T>() { companion object }
open class local<T>: File<T>() { companion object }
companion object { fun uri(path: Any) = println(path) }
}
operator fun bin<localhost_>.div(a: sh.Companion) = sh<bin<localhost_>>()
operator fun bin<usr<localhost_>>.div(a: vim.Companion) = vim<bin<usr<localhost_>>>()
operator fun etc<localhost_>.div(a: vim.Companion) = vim<etc<localhost_>>()
operator fun usr<localhost_>.div(a: bin.Companion) = bin<usr<localhost_>>()
operator fun usr<localhost_>.div(a: local.Companion) = local<usr<localhost_>>()
operator fun local<usr<localhost_>>.div(a: bin.Companion) = bin<local<usr<localhost_>>>()
/**
* localhost_/
* ├── bin/
* │ └── sh
* ├── etc/
* │ └── vim
* └── usr/
* ├── bin/
* │ └── vim
* └── local/
* └── bin/
*/
fun main(a: Array<String>) {
//Compiles!
Y.uri(localhost_)
Y.uri(localhost_/bin)
Y.uri(localhost_/bin/sh)
Y.uri(localhost_/etc)
Y.uri(localhost_/etc/vim)
Y.uri(localhost_/usr)
Y.uri(localhost_/usr/bin/vim)
Y.uri(localhost_/usr/local)
Y.uri(localhost_/usr/local/bin)
//Does not compile!
Y.uri(localhost_/local)
Y.uri(localhost_/bin/vim)
Y.uri(localhost_/sh)
Y.uri(localhost_/bin/local)
Y.uri(localhost_/etc/local)
Y.uri(localhost_/etc/sh)
Y.uri(localhost_/usr/local/usr)
}
导入Y*
抽象类文件
开放类Y私有构造函数(){
开放类localhost\u{
@JvmName(“usr”)操作符fun div(a:usr.Companion)=usr()
@JvmName(“bin”)操作员fun div(a:bin.Companion)=bin()
@JvmName(“etc”)操作员fun div(a:etc同伴)=etc()
伴生对象:localhost(()
}
打开类bin:File(){companion object}
打开类sh:File(){companion object}
打开类etc:File(){companion object}
打开类vim:File(){companion object}
打开类usr:File(){companion object}
打开本地类:File(){companion object}
伴随对象{fun uri(路径:Any)=println(路径)}
}
操作员趣味箱分区(a:sh.Companion)=sh()
操作员娱乐箱分区(a:vim.Companion)=vim()
操作员娱乐等部门(a:vim.Companion)=vim()
操作员乐趣usr.div(a:bin.Companion)=bin()
操作员fun usr.div(a:local.Companion)=local()
操作符fun local.div(a:bin.Companion)=bin()
/**
*本地主机_/
* ├── 垃圾箱/
* │ └── 嘘
* ├── 等/
* │ └── 维姆
* └── usr/
* ├── 垃圾箱/
* │ └── 维姆
* └── 本地的/
* └── 垃圾箱/
*/
趣味主打(a:阵列){
//编译!
Y.uri(本地主机)
Y.uri(localhost\uu/bin)
Y.uri(localhost\uu/bin/sh)
Y.uri(本地主机\等)
Y.uri(localhost\u/etc/vim)
Y.uri(localhost\uu/usr)
Y.uri(localhost\uu/usr/bin/vim)
Y.uri(localhost\uu/usr/local)
Y.uri(localhost\uu/usr/local/bin)
//不编译!
Y.uri(本地主机\本地)
Y.uri(localhost\uu/bin/vim)
Y.uri(localhost\ush/sh)
Y.uri(localhost\u/bin/local)
Y.uri(localhost\u/etc/local)
Y.uri(localhost\uu/etc/sh)
Y.uri(localhost\uu/usr/local/usr)
}
如何将接收器具有泛型类型的扩展函数转换为成员函数?有没有办法将运算符函数放入类中,或者扩展是实现这一点的唯一方法?我尝试过类似的方法,但不起作用:
open class usr<T>: File<T>() {
operator fun <T: usr<localhost_>> div(a: local.Companion) = local<T>()
operator fun <T: usr<localhost_>> div(a: bin.Companion) = bin<T>()
companion object
}
开放类usr:File(){
操作员乐趣分区(a:local.Companion)=本地()
操作员娱乐部(a:bin.Companion)=bin()
伴星
}
首先,让我说一下:这是对除法运算符函数的一种相当明显的误用。仅仅为了使用/
而忽略除数的除法?然而,老实说,在代码中使用/
也是一种有趣的方式;-)不过,我不能推荐它。看看你的代码。您现在有很多未使用的除数;-)撇开免责声明不谈,让我们来解决您的问题
你具体问题的解决方案并不像你想象的那么好。您对扩展函数所做的操作并不容易移动到成员函数。原因:您将扩展函数的使用范围缩小到特定的泛型类型。如果你想成为同一个会员,你也需要缩小范围。如果查看扩展函数是什么(静态方法调用),那么在实现类中可能还需要相同的结构。例如,以下示例可行,但并未缩小层次结构:
open class usr<T>: File<T>() {
operator fun div(a: local.Companion) = local<usr<T>>()
operator fun div(a: bin.Companion) = bin<usr<T>>()
companion object
}
但是,调用它确实不好看(因为您需要导入适当的类型…您仍然可以将leaf放在类层次结构之外,但这实际上并不相同;-)(现在vim
是一个leaf,但是如果您有一个文件夹vim
以后呢?)
但是,同样,由于您没有使用除法作为除法,您可能还是最好省略它(因为您甚至没有获得漂亮/有用的代码完成),例如,通过使用:
Y.uri("localhost_/usr/local/bin")
或者使用具体化类型和连接路径的StringBuilder
:
abstract class File {
val uri = StringBuilder()
inline fun <reified T> append() : T {
val clazz = T::class
uri.append(clazz.simpleName).append("/")
return clazz.java.newInstance()
}
}
open class usr: File() {
fun local() = append<local>()
fun bin() = append<bin>()
}
通过这种方式,您甚至可以完成有用的代码
下面是一个示例,我仍然不推荐它,它使用操作符和后面的具体化函数的混合:
open class usr: File() {
operator fun div(a : local.Companion) = append<local>()
operator fun div(a : bin.Companion) = append<bin>()
companion object
}
开放类usr:File(){
操作符fun div(a:local.Companion)=append()
运算符fun div(a:bin.Companion)=追加()
伴星
}
请注意,您也可以将重新填充的类型与运算符混合使用,但您需要一个内联
函数。我没有进一步详细说明;-)
正如你自己指出的,你甚至可以使用属性。。。真的有很多事情你应该考虑,而不是滥用泛型和划分;p> 感谢您详细周到的回复。我对你的解决方案很感兴趣,但读了几遍之后,我看不出它是如何解决问题的。也许我不够聪明。你写道,“为什么不先省略泛型类型信息?如果你在任何地方删除它,你的代码仍然会像你期望的那样工作。”。这句话完全不真实(试试看)。主函数必须按描述的那样工作。我愿意使用函数调用,但同样,主函数必须按描述的那样工作。下面是使用您的语法的规范。编译:
localhost().bin()
,localhost().bin().sh()
,localhost().usr().bin()
。不编译:localhost().usr().bin().sh()
。作为参考,您可以在这里找到我的解决方案:我非常确定我测试了您的所有主要条目。我稍后会看一看。也许我错过了一份;-)验证解决方案时,所有“Compiles!”语句都要编译,而“not compile!”语句都不编译,这一点很重要。
abstract class File {
val uri = StringBuilder()
inline fun <reified T> append() : T {
val clazz = T::class
uri.append(clazz.simpleName).append("/")
return clazz.java.newInstance()
}
}
open class usr: File() {
fun local() = append<local>()
fun bin() = append<bin>()
}
Y.uri(localhost().usr().local().bin())
// or simply localhost().usr().local().bin().uri
open class usr: File() {
operator fun div(a : local.Companion) = append<local>()
operator fun div(a : bin.Companion) = append<bin>()
companion object
}