用Java模拟指针?在科特林?

我正在尝试模拟另一种晦涩的编程范例中使用的一种指针,因此我可以将一些代码移植到 Java。另一种语言不是面向对象的,而是受到 Pascal 的粗略启发。


在原始语言中,我们可以编写这样的代码。首先,使用文本。


// Start with text.

Text myVar = "Bonjour" 

Pointer myPointer = ->myVar       // Referencing a string variable, storing the reference in another variable of type `Pointer`.

Message( myPointer-> )    // Dereferencing the pointer, to retrieve `myVar`, and pass the string to a command `Display` that displays the message on screen in a dialog box.

然后,切换到数字。


// Switch gears, to work with an number.

Integer vResult = ( Random % ( vEnd - vStart + 1 ) ) + vStart  // Generate random number.

myPointer = ->vResult    // The same pointer now points to numeric variable rather than a textual variable. 

我们可以通过变量名的文本来分配一个指针。


myPointer = Get pointer( "var" + String($i) ) // Generate pointer variable named `var1`, or `var2`, etc.

我们可以向指针询问一个代码号,该代码号表示它所指向的值的数据类型(所指对象的数据类型)。


typeCodeNumber = Type( myPointer ) // Returns 11 for an integer, 22 for text.

在另一种语言中,编译器确实提供了类型安全。但是当以这种方式使用指针时,我们牺牲了类型安全。编译器会发出警告,指出代码使用在类型方面不明确。


我移植此代码的想法是定义一个XPointer类以及为XText和等类型定义的类XInteger。


我需要持有对十几种特定已知类型中任何一种的对象的引用,包括对另一个指针的引用。我可以硬编码十几种类型,不需要对所有类型开放。


这十几种类型不共享接口或抽象类,除了Object. 即使它们确实共享一个接口/超类,我也不希望它们作为超类返回,而是作为它们原来的具体类返回。当他们进入指针时,他们也应该从指针中出现。


我目前的计划是XPointer用一对引用和取消引用方法在 Java 中定义一个类:


XPointer::ref( x )在哪里传递, 或class 的对象Dog,甚至是另一个对象。TruckSculptureXPointer

XPointer::deref ⇒ x其中 x 是一个被识别为其原始类型的对象,a Dog, aTruck或 aSculpture甚至另一个XPointer对象,而不仅仅是一个Object对象。

➥ 有没有办法做这个Java?也许与泛型?


➥ 如果在 Java 中不可能,我可以不情愿地切换到 Kotlin。这个指针功能可以在JVM上运行的Kotlin中完成吗?


斯蒂芬大帝
浏览 112回答 3
3回答

当年话下

这称为联合或变体类型(请参阅C++ 中的Boost.Variant)。后者特别方便,因为它是一组异构类型的类型安全容器,并且最接近您对要移植的代码类型的描述。由于 Java 不支持模板——不,泛型不是模板——你不会得到你正在寻找的东西。Optional类型是两种类型中最简单的情况:类型 T 和 Null 。鉴于您需要存储的不仅仅是 T 或 Null 类型,它对您不起作用。您可能想查看JavaSealedUnions。此外,Kotlin 提供了密封类的概念,有助于将值限制为受约束集中的一种类型。

ITMISS

这是我能想到的最好的。我认为你不能轻易地制作一个通用类型,而不是它是所有类的父类(如对象)。考虑到类型系统,转换也很困难,您可以通过不允许重新分配不同类型的指针来模仿它,而每次执行获取时只生成一个新指针。如果你不想知道类型本身,你可以在现代 java 中使用 var 来隐藏类型差异。public class Types {&nbsp; &nbsp; public static void main(String[] args) {&nbsp; &nbsp; &nbsp; &nbsp; var p = new PascalPointer<>(new PascalInt());&nbsp; &nbsp; &nbsp; &nbsp; PascalInt i = p.get();&nbsp; &nbsp; &nbsp; &nbsp; var p2 = new PascalPointer<>(i.toPStr()); // mimic generics by type inference.&nbsp; &nbsp; &nbsp; &nbsp; PascalString s = p2.get();&nbsp; &nbsp; &nbsp; &nbsp; PascalPointer<PascalType> genericPointer = new PascalPointer<>(s);&nbsp; &nbsp; &nbsp; &nbsp; genericPointer.set(i);&nbsp; &nbsp; &nbsp; &nbsp; var i2 = (PascalInt) genericPointer.get();&nbsp; &nbsp; }&nbsp; &nbsp; public interface PascalType { }&nbsp; &nbsp; public static class PascalInt implements PascalType {&nbsp; &nbsp; &nbsp; &nbsp; // cast&nbsp; &nbsp; &nbsp; &nbsp; public PascalString toPStr() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new PascalString(); // hide a new to do a conversion instead of a cast really.&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; public static class PascalString implements PascalType { }&nbsp; &nbsp; public static class PascalPointer<T extends PascalType> {&nbsp; &nbsp; &nbsp; &nbsp; T t;&nbsp; &nbsp; &nbsp; &nbsp; public PascalPointer(T t) { this.t = t; }&nbsp; &nbsp; &nbsp; &nbsp; public T get() { return t;}&nbsp; &nbsp; &nbsp; &nbsp; public void set(T t) {this.t = t;}&nbsp; &nbsp; }}当您想要一个字符串的 Int 视图并更新字符串时,这可能会发生故障(正如我在这里复制的那样)。

德玛西亚99

对于冗长的回答,我深表歉意。我不认为你可以在不失去类型安全的情况下使用泛型实现你想要的。为了使下一行工作,Java 需要知道Truck该方法返回了一个,defer()以便它可以调用honk()该对象。p.deref().honk();但是,如果您使用 Java 泛型,那么这会在编译时推断出类型擦除。该解决方案意味着添加一个通用类型,例如Pointer<Truck>,但我们不能,因为您希望能够添加十几个特定的已知类型和一个Pointer.但是......由于您自己编写了这样的行,特别是调用bark()orhonk(),这意味着您已经知道Pointer引用 aDogorTruck对象。使用该假设、泛型和对 的修改defer(),您可以非常接近解决方案。假设我们有这些类,它们没有任何链接。public class Dog {&nbsp; &nbsp; public void bark() {&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Bark ...");&nbsp; &nbsp; }}public class Truck {&nbsp; &nbsp; public void honk() {&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Honk ...");&nbsp; &nbsp; }}然后我们需要一个像这样的Pointer类,其中deref()方法需要一个Class参数来知道要返回哪个类型。public class Pointer {&nbsp; &nbsp; private Object myObj;&nbsp; &nbsp; public <T> void ref(T myObject) {&nbsp; &nbsp; &nbsp; &nbsp; this.myObj = myObject;&nbsp; &nbsp; }&nbsp; &nbsp; public <T> T deref(Class<T> myClazz) {&nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return myClazz.cast(myObj);&nbsp; &nbsp; &nbsp; &nbsp; } catch(ClassCastException e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}然后您可以执行以下操作public static void main(String[] args) {&nbsp; &nbsp; Pointer pointer = new Pointer();&nbsp; &nbsp; Dog dog = new Dog();&nbsp; &nbsp; pointer.ref(dog);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Reference to a Dog&nbsp; &nbsp; pointer.deref(Dog.class).bark();&nbsp; &nbsp; Truck truck = new Truck();&nbsp; &nbsp; pointer.ref(truck);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Reference to a Truck&nbsp; &nbsp; pointer.deref(Truck.class).honk();&nbsp; &nbsp; Pointer subPointer = new Pointer();&nbsp; &nbsp; pointer.ref(subPointer);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Reference to another pointer&nbsp; &nbsp; subPointer.ref(truck);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Other pointer references a Truck&nbsp; &nbsp; pointer.deref(Pointer.class).deref(Truck.class).honk();&nbsp; &nbsp; subPointer.ref(dog);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Other pointer references a Dog&nbsp; &nbsp; pointer.deref(Pointer.class).deref(Dog.class).bark();&nbsp; &nbsp; pointer.ref(null);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Clears the reference&nbsp; &nbsp; Truck bulldog = new Truck();&nbsp; &nbsp; pointer.ref(bulldog);&nbsp; &nbsp; pointer.deref(Dog.class).bark();&nbsp; &nbsp;// Is allowed, but will cause a NullPointerException}这将打印出:Bark ...Honk ...Honk ...Bark ...在 Pointer.main(Pointer.java:39) 的线程“主”java.lang.NullPointerException 中出现异常如果您需要将Pointer引用限制为仅对您的十几个特定已知类型和Pointer类本身,那么您需要使用超类(例如Pointerable)扩展它们并相应地修改ref()方法。然后,您可以防止不扩展此超类的类型被您的指针引用。例子:public abstract class Pointerable { }public class Dog extends Pointerable {&nbsp; &nbsp; public void bark() {&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Bark ...");&nbsp; &nbsp; }}public class Pointer extends Pointerable {&nbsp; &nbsp; private Object myObj;&nbsp; &nbsp; public <T extends Pointerable> void ref(T myObject) {&nbsp; &nbsp; &nbsp; &nbsp; this.myObj = myObject;&nbsp; &nbsp; }&nbsp; &nbsp; public <T extends Pointerable> T deref(Class<T> myClazz) {&nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return myClazz.cast(myObj);&nbsp; &nbsp; &nbsp; &nbsp; } catch(ClassCastException e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java