Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin 如何确保一个类只能用另一个类的对象实例化,而不暴露内部?_Kotlin - Fatal编程技术网

Kotlin 如何确保一个类只能用另一个类的对象实例化,而不暴露内部?

Kotlin 如何确保一个类只能用另一个类的对象实例化,而不暴露内部?,kotlin,Kotlin,假设我们有两门课,Foo和Bar。 条形图只能从Foo对象构造 下面是我目前的尝试,说明为什么我不认为它们是正确的解决方案: 尝试1: class Foo { var data: Int = 0 // meh: This implementation detail should not be exposed to the public. fun add(x: Int) { data += x } } class Bar(foo: Foo) { p

假设我们有两门课,Foo和Bar。 条形图只能从Foo对象构造

下面是我目前的尝试,说明为什么我不认为它们是正确的解决方案:

尝试1:

class Foo {
    var data: Int = 0 // meh: This implementation detail should not be exposed to the public.
    fun add(x: Int) {
        data += x
    }
}

class Bar(foo: Foo) {
    private var data: Int = 2 * foo.data
    fun show() = println(data + 10)
}

fun main() {
    val myFoo = Foo()
    myFoo.add(3)
    myFoo.add(4)
    val myBar = Bar(myFoo)
    myBar.show()
}
问题:Foo::数据不应从外部可见

尝试2:

class Foo {
    private var data: Int = 0
    fun add(x: Int) {
        data += x
    }

    fun makeBar() = Bar(2 * data)
}

class Bar(private val data: Int) { // meh: Bar should only be instantiated from a Foo.
    fun show() = println(data + 10)
}

fun main() {
    val myFoo = Foo()
    myFoo.add(3)
    myFoo.add(4)
    val myBar = myFoo.makeBar()
    myBar.show()
}
问题:现在每个人都可以创建一个酒吧,即使手边没有食物


来自C++的第一个想法是让BAR的构造器私有化,但是只让Foo通过声明它是一个类来访问它。Kotlin中是否有类似的功能,或者是否有其他更好的解决方案?

阅读您的用例时,您可能正在寻找一个更好的解决方案。以下是您第一次尝试使用内部类栏时得出的解决方案:

正如你所说,你更喜欢高水平的课程。根据您希望Foo.data的安全程度,您可能还对以下设置感兴趣:

class Foo {
    private var data = 0
    fun add(x: Int) {
        data += x
    }
    fun Bar.getFooData() = data
}

class Bar(foo: Foo) {
    private var data = 2 * with(foo) { getFooData() }
    fun show() = println(data + 10)
}
因此,只有当您同时拥有一个Bar和一个Foo(后者作为接收器)时,才能访问Foo的数据。但是,这也意味着,如果两个对象都对您可用,您可以从外部访问Foo.data,例如,以下操作也将主要成功:


所以:忽略反射、嵌套或内部类使数据从外部不可访问是您的朋友。使其更难访问或:强制某些条件为真,在使用它之前,具有适当接收器的扩展函数方法可能是您的朋友。

阅读您的用例时,您可能正在寻找一个合适的方法。以下是您第一次尝试使用内部类栏时得出的解决方案:

正如你所说,你更喜欢高水平的课程。根据您希望Foo.data的安全程度,您可能还对以下设置感兴趣:

class Foo {
    private var data = 0
    fun add(x: Int) {
        data += x
    }
    fun Bar.getFooData() = data
}

class Bar(foo: Foo) {
    private var data = 2 * with(foo) { getFooData() }
    fun show() = println(data + 10)
}
因此,只有当您同时拥有一个Bar和一个Foo(后者作为接收器)时,才能访问Foo的数据。但是,这也意味着,如果两个对象都对您可用,您可以从外部访问Foo.data,例如,以下操作也将主要成功:


所以:忽略反射、嵌套或内部类使数据从外部不可访问是您的朋友。使其更难访问或:强制某些条件为真,在使用它之前,具有适当接收器的扩展函数方法可能是您的朋友。

我认为您可以在不同的模块中创建Foo Bar类,并使Foo::data成为内部的。。所以它只在那个模块上可见。。对于其余的模块,它是不可访问的。使Bar成为Foo的内部类?我认为您可以在不同的模块中创建Foo-Bar类,并使Foo::data成为内部类。。所以它只在那个模块上可见。。对于其余的模块,它是不可访问的。使Bar成为Foo的内部类?谢谢。另一个基于类似想法的解决方案如下所示。我更希望这门课是高水平的,但我想这是我们能得到的最好的了。@TobiasHermann好的。然而,在这种特殊情况下,我认为您最好只使用内部类。如果Foo.data只能由bar的实例访问,对您来说可以吗?如果是这样的话,您可能还想在Foo中使用扩展函数,例如fun Bar.getData=data,这基本上使它对任何Bar实例都可见。。。我会更新答案以显示我的意思…再次感谢。这是您的编辑时间:我想我更喜欢内部/嵌套类版本。但这将把构建酒吧的逻辑转移到了Foo中。所以我更喜欢Foo里面的版本栏。谢谢。另一个基于类似想法的解决方案如下所示。我更希望这门课是高水平的,但我想这是我们能得到的最好的了。@TobiasHermann好的。然而,在这种特殊情况下,我认为您最好只使用内部类。如果Foo.data只能由bar的实例访问,对您来说可以吗?如果是这样的话,您可能还想在Foo中使用扩展函数,例如fun Bar.getData=data,这基本上使它对任何Bar实例都可见。。。我会更新答案以显示我的意思…再次感谢。这是您的编辑时间:我想我更喜欢内部/嵌套类版本。但这将把构建酒吧的逻辑转移到了Foo中。所以我更喜欢Foo里面的版本栏。
with (myFoo) {
  myBar.getFooData()
}