亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

用Java模擬指針?在科特林?

用Java模擬指針?在科特林?

斯蒂芬大帝 2022-07-06 18:51:25
我正在嘗試模擬另一種晦澀的編程范例中使用的一種指針,因此我可以將一些代碼移植到 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,甚至是另一個對象。TruckSculptureXPointerXPointer::deref ? x其中 x 是一個被識別為其原始類型的對象,a Dog, aTruck或 aSculpture甚至另一個XPointer對象,而不僅僅是一個Object對象。? 有沒有辦法做這個Java?也許與泛型?? 如果在 Java 中不可能,我可以不情愿地切換到 Kotlin。這個指針功能可以在JVM上運行的Kotlin中完成嗎?
查看完整描述

3 回答

?
當年話下

TA貢獻1890條經驗 獲得超9個贊

這稱為聯合變體類型(請參閱C++ 中的Boost.Variant)。后者特別方便,因為它是一組異構類型的類型安全容器,并且最接近您對要移植的代碼類型的描述。由于 Java 不支持模板——不,泛型不是模板——你不會得到你正在尋找的東西。

Optional類型是兩種類型中最簡單的情況:類型 T 和 Null 。鑒于您需要存儲的不僅僅是 T 或 Null 類型,它對您不起作用。

您可能想查看JavaSealedUnions。此外,Kotlin 提供了密封類的概念,有助于將值限制為受約束集中的一種類型。


查看完整回答
反對 回復 2022-07-06
?
ITMISS

TA貢獻1871條經驗 獲得超8個贊

這是我能想到的最好的。我認為你不能輕易地制作一個通用類型,而不是它是所有類的父類(如對象)??紤]到類型系統,轉換也很困難,您可以通過不允許重新分配不同類型的指針來模仿它,而每次執行獲取時只生成一個新指針。如果你不想知道類型本身,你可以在現代 java 中使用 var 來隱藏類型差異。


public class Types {

    public static void main(String[] args) {

        var p = new PascalPointer<>(new PascalInt());

        PascalInt i = p.get();

        var p2 = new PascalPointer<>(i.toPStr()); // mimic generics by type inference.

        PascalString s = p2.get();

        PascalPointer<PascalType> genericPointer = new PascalPointer<>(s);

        genericPointer.set(i);

        var i2 = (PascalInt) genericPointer.get();

    }

    public interface PascalType { }


    public static class PascalInt implements PascalType {

        // cast

        public PascalString toPStr() {

            return new PascalString(); // hide a new to do a conversion instead of a cast really.

        }

    }


    public static class PascalString implements PascalType { }


    public static class PascalPointer<T extends PascalType> {

        T t;

        public PascalPointer(T t) { this.t = t; }

        public T get() { return t;}

        public void set(T t) {this.t = t;}

    }


}

當您想要一個字符串的 Int 視圖并更新字符串時,這可能會發生故障(正如我在這里復制的那樣)。


查看完整回答
反對 回復 2022-07-06
?
德瑪西亞99

TA貢獻1770條經驗 獲得超3個贊

對于冗長的回答,我深表歉意。

我不認為你可以在不失去類型安全的情況下使用泛型實現你想要的。


為了使下一行工作,Java 需要知道Truck該方法返回了一個,defer()以便它可以調用honk()該對象。


p.deref().honk();

但是,如果您使用 Java 泛型,那么這會在編譯時推斷出類型擦除。

該解決方案意味著添加一個通用類型,例如Pointer<Truck>,但我們不能,因為您希望能夠添加十幾個特定的已知類型和一個Pointer.


但是......由于您自己編寫了這樣的行,特別是調用bark()orhonk(),

這意味著您已經知道Pointer引用 aDogorTruck對象。


使用該假設、泛型和對 的修改defer(),您可以非常接近解決方案。


假設我們有這些類,它們沒有任何鏈接。


public class Dog {

    public void bark() {

        System.out.println("Bark ...");

    }

}


public class Truck {

    public void honk() {

        System.out.println("Honk ...");

    }

}

然后我們需要一個像這樣的Pointer類,其中deref()方法需要一個Class參數來知道要返回哪個類型。


public class Pointer {


    private Object myObj;


    public <T> void ref(T myObject) {

        this.myObj = myObject;

    }


    public <T> T deref(Class<T> myClazz) {

        try {

            return myClazz.cast(myObj);

        } catch(ClassCastException e) {

            return null;

        }

    }

}

然后您可以執行以下操作


public static void main(String[] args) {

    Pointer pointer = new Pointer();


    Dog dog = new Dog();

    pointer.ref(dog);                  // Reference to a Dog

    pointer.deref(Dog.class).bark();


    Truck truck = new Truck();

    pointer.ref(truck);                // Reference to a Truck

    pointer.deref(Truck.class).honk();


    Pointer subPointer = new Pointer();

    pointer.ref(subPointer);           // Reference to another pointer

    subPointer.ref(truck);             // Other pointer references a Truck

    pointer.deref(Pointer.class).deref(Truck.class).honk();

    subPointer.ref(dog);               // Other pointer references a Dog

    pointer.deref(Pointer.class).deref(Dog.class).bark();


    pointer.ref(null);                 // Clears the reference


    Truck bulldog = new Truck();

    pointer.ref(bulldog);

    pointer.deref(Dog.class).bark();   // 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 {

    public void bark() {

        System.out.println("Bark ...");

    }

}


public class Pointer extends Pointerable {


    private Object myObj;


    public <T extends Pointerable> void ref(T myObject) {

        this.myObj = myObject;

    }


    public <T extends Pointerable> T deref(Class<T> myClazz) {

        try {

            return myClazz.cast(myObj);

        } catch(ClassCastException e) {

            return null;

        }

    }


查看完整回答
反對 回復 2022-07-06
  • 3 回答
  • 0 關注
  • 132 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號