21

「Julia では、従来の「クラス」をシングル ディスパッチ スタイルのメソッドで作成することはできない」という本を読んだのですが、obj.myfunc()それは事実というよりは挑戦のように聞こえると思いました。

だからJavaClass、開発者がそれを避けるために行ったすべての問題の後、ジュリアでこのような醜いものを持っているというまったくのショックと恐怖の要因のためだけに、パブリック/プライベートフィールドとメソッドを使用した私の型があります:

type JavaClass

    # Public fields
    name::String

    # Public methods
    getName::Function
    setName::Function
    getX::Function
    getY::Function
    setX::Function
    setY::Function

    # Primary Constructor - "through Whom all things were made."
    function JavaClass(namearg::String, xarg::Int64, yarg::Int64)

        # Private fields - implemented as "closed" variables
        x = xarg
        y = yarg

        # Private methods used for "overloading"
        setY(yarg::Int64) = (y = yarg; return nothing)
        setY(yarg::Float64) = (y = Int64(yarg * 1000); return nothing)

        # Construct object
        this = new()
        this.name = namearg
        this.getName = () -> this.name
        this.setName = (name::String) -> (this.name = name; return nothing)
        this.getX = () -> x
        this.getY = () -> y
        this.setX = (xarg::Int64) -> (x = xarg; return nothing)
        this.setY = (yarg) -> setY(yarg) #Select appropriate overloaded method

        # Return constructed object
        return this
    end

    # a secondary (inner) constructor
    JavaClass(namearg::String) = JavaClass(namearg, 0,0)
end

使用例:

julia> a = JavaClass("John", 10, 20);

julia> a.name # public
"John"

julia> a.name = "Jim";

julia> a.getName()
"Jim"

julia> a.setName("Jack")

julia> a.getName()
"Jack"

julia> a.x # private, cannot access
ERROR: type JavaClass has no field x

julia> a.getX()
10

julia> a.setX(11)

julia> a.getX()
11

julia> a.setY(2) # "single-dispatch" call to Int overloaded method

julia> a.getY()
2

julia> a.setY(2.0)

julia> a.getY()  # "single-dispatch" call to Float overloaded method
2000

julia> b = JavaClass("Jill"); # secondary constructor

julia> b.getX()
0

基本的に、コンストラクターはクロージャーになります。これは、「プライベート」フィールドとメソッド/オーバーロードを作成する方法です。何かご意見は?( 「OMG Why??? なぜこれを行うのですか??」以外)
他のアプローチはありますか?
これが見事に失敗する可能性があると想定できるシナリオはありますか?

4

2 に答える 2

39

もちろん、これは Julia でオブジェクトとメソッドを作成するための慣用的な方法ではありませんが、ひどく悪いことも何もありません。クロージャを持つどの言語でも、このように独自の「オブジェクト システム」を定義できます。たとえば、Scheme 内で開発された多くのオブジェクト システムを参照してください。

julia v0.5 では、クロージャがキャプチャされた変数をオブジェクト フィールドとして自動的に表すため、これを行うための特に巧妙な方法があります。例えば:

julia> function Person(name, age)
        getName() = name
        getAge() = age
        getOlder() = (age+=1)
        ()->(getName;getAge;getOlder)
       end
Person (generic function with 1 method)

julia> o = Person("bob", 26)
(::#3) (generic function with 1 method)

julia> o.getName()
"bob"

julia> o.getAge()
26

julia> o.getOlder()
27

julia> o.getAge()
27

これを行うために関数を返さなければならないのは奇妙ですが、それはあります。これは、言語が正確なフィールド タイプを判断するなど、多くの最適化の恩恵を受けているため、場合によっては、これらの「メソッド呼び出し」をインライン化することもできます。もう 1 つの優れた機能は、関数の最終行がどのフィールドを「パブリック」にするかを制御することです。そこにリストされているものはすべて、オブジェクトのフィールドになります。この場合、name 変数と age 変数ではなく、メソッドのみを取得します。しかし、リストに追加した場合は、同様nameに行うことができます。o.nameもちろん、メソッドもマルチメソッドです。などに複数の定義を追加するgetOlderと、期待どおりに機能します。

于 2016-08-25T16:34:48.900 に答える