编辑:我在结尾提供了解决问题的JAVA代码。
我想知道如何在Kotlin中创建一个私有嵌套类,以便可以从它的父类访问它,但不能从其他任何地方访问它。
在下面的代码片段中,我用“//(!)"标记了发生编译错误的行。
class Sphere(val radius: Double = 1.toDouble()) {
var pointsLinkedHashSet: LinkedHashSet<Point> = linkedSetOf()
//(!)'public' property exposes its 'private-in-class' type argument Point (make "Point" public)
fun getPoints(): LinkedHashSet<Point> {
return pointsLinkedHashSet
}
//(!) 'public' function exposes its 'private-in-class' return type argument Point (make "Point" public)
fun getLastPoint(): Point = pointsLinkedHashSet.last()
//(!) Same as previous
fun clearPoints() = pointsLinkedHashSet.clear()
fun addPoint(radius: Double = this.radius, latitude: Double, longitude: Double): Point {
val point = Point(radius, latitude, longitude)
pointsLinkedHashSet.add(point)
return point
}
//(!) Same as previous
private class Point(
val radius: Double,
val latitude: Double,
val longitude: Double
)
}
换句话说,这是我的Main类:
class Main {
companion object {
@JvmStatic
fun main(args: Array<String>) {
val sphere = Sphere()
val point = sphere.addPoint(10.toDouble(), 10.toDouble(), 10.toDouble()) //this works as it should
val point1 = sphere.getLastPoint() // this too
val point2 = Sphere.Point(10.toDouble(), 10.toDouble(), 10.toDouble()) //this doesn't work because Point is private, as it should
val radius = point.radius //same in these next 3 lines
val latitude = point.latitude
val longitude = point.longitude
}
}
}
我已经在代码注解中描述了所需的行为。
这在Java中很容易实现,但在Kotlin中我还找不到一种方法来实现它,而且找不到任何与这个问题相关的文章,尽管它很容易遇到。
还是我漏掉了什么明显的东西?你能帮忙吗?谢谢。
使用JAVA代码更新:
球体类:
package org.example;
import java.util.LinkedHashSet;
public class Sphere {
private final Double radius;
private final LinkedHashSet<Point> pointsLinkedHashSet = new LinkedHashSet<Point>();
public Double getRadius() {
return this.radius;
}
public Sphere(Double radius) {
this.radius = radius;
}
public Point getLastPoint() {
if (pointsLinkedHashSet.isEmpty()) return null;
return (Point) pointsLinkedHashSet.toArray()[pointsLinkedHashSet.size() - 1];
}
public Point addPoint(Double latitude, Double longitude) {
Point point = new Point(latitude, longitude);
pointsLinkedHashSet.add(point);
return point;
}
class Point {
private final Double radius;
private final Double latitude;
private final Double longitude;
Double getLatitude() {
return latitude;
}
Double getLongitude() {
return longitude;
}
Double getRadius() {
return this.radius;
}
private Point(Double latitude, Double longitude) {
this.radius = Sphere.this.radius;
this.latitude = latitude;
this.longitude = longitude;
}
}
}
主类:
package org.example;
public class Main {
public static void main(String[] args) {
Sphere sphere = new Sphere(1.0);
System.out.println("Sphere radius = " + sphere.getRadius());
Sphere.Point point = sphere.addPoint(10.0,10.0);
System.out.println("Point radius = " + point.getRadius());
System.out.println("Point latitude = " + point.getLatitude());
System.out.println("Point longitude = " + point.getLongitude());
// Sphere.Point point = new Sphere.Point(10.0,10.0); does not work
// can not create new Point object because its constructor is private,
// this is desired behaviour!
Sphere.Point point1 = sphere.getLastPoint();
System.out.println("Point1 radius = " + point1.getRadius());
System.out.println("Point1 latitude = " + point1.getLatitude());
System.out.println("Point1 longitude = " + point1.getLongitude());
}
}
输出量:
Sphere radius = 1.0
Point radius = 1.0
Point latitude = 10.0
Point longitude = 10.0
Point1 radius = 1.0
Point1 latitude = 10.0
Point1 longitude = 10.0
1条答案
按热度按时间1rhkuytd1#
令人困惑的是,你的请求根本就不是一个私有类。私有类是一个完全不能从文件外部访问的类,所以从文件中的任何公共函数返回它作为一个类型是没有意义的。Java中也是如此。
你的Java代码并没有把Point私有化,它只是把它的构造函数私有化,所以我猜你真正想要的是防止Point类从这个文件之外示例化。
在Kotlin中似乎没有一种方法可以复制这种行为。(Discussion here)最接近的方法是将构造函数标记为
internal
。或者,将类标记为
inner
就足够了,这样类就不能在没有外部类的上下文的情况下示例化。可以调用someSphereInstance.Point(...)
,但不能调用Sphere.Point(...)
。注意,将嵌套类设为
inner
会使它更像Java代码。这两种类型的嵌套类在Java和Kotlin中的声明是不同的:嵌套类的修饰符关键字:
| | 绑定到外部类示例|独立于外部示例|
| - -|- -|- -|
|** java *| 无 *|
static
|| "Kotlin"|
inner
| * 无 *|