如何创建一个“单一调度、面向对象的类"?在 julia 中,它的行为类似于具有公共/私有字段和方法的标准 Java 类 [英] How to create a "single dispatch, object-oriented Class" in julia that behaves like a standard Java Class with public / private fields and methods

查看:19
本文介绍了如何创建一个“单一调度、面向对象的类"?在 julia 中,它的行为类似于具有公共/私有字段和方法的标准 Java 类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一本书中读到你不能在 julia 中使用像 obj.myfunc() 这样的单一调度风格的方法创建传统的‘类’"......我认为这听起来与其说是事实,不如说是挑战.

I read in a book that "you can't create traditional 'classes' in julia with single-dispatch-style methods like obj.myfunc()" ... and I thought that sounded more like a challenge than a fact.

所以这是我的 JavaClass 类型,它带有公共/私有字段和方法,只是为了在 Julia 中出现这样丑陋的东西时的震惊和恐怖因素,毕竟开发人员已经避免了所有麻烦它:

So here's my JavaClass type with public / private fields and methods just for the sheer shock and horror factor of having something ugly like this in Julia, after all the trouble the devs have gone to to avoid it:

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 为什么???你为什么要这样做??")
还有其他方法吗?
您可以设想什么情况下这可能会严重失败?

Essentially, the constructor becomes a closure, which is how one creates "private" fields and methods / overloading. Any thoughts? (other than "OMG Why??? Why would you do this??")
Any other approaches?
Any scenarios you could envisage where this might fail spectacularly?

推荐答案

虽然这当然不是在 julia 中创建对象和方法的惯用方式,但它也没有什么可怕的问题.在任何带有闭包的语言中,您都可以像这样定义自己的对象系统",例如查看在 Scheme 中开发的许多对象系统.

While of course this isn't the idiomatic way to create objects and methods in julia, there's nothing horribly wrong with it either. In any language with closures you can define your own "object systems" like this, for example see the many object systems that have been developed within Scheme.

在 julia v0.5 中,有一种特别巧妙的方法可以做到这一点,因为闭包会自动将其捕获的变量表示为对象字段.例如:

In julia v0.5 there is an especially slick way to do this due to the fact that closures represent their captured variables as object fields automatically. For example:

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

您必须返回一个函数才能执行此操作,这很奇怪,但它确实存在.这得益于许多优化,例如为您确定精确字段类型的语言,因此在某些情况下,我们甚至可以内联这些方法调用".另一个很酷的功能是该功能的底线控制哪些字段是公共的";那里列出的任何内容都将成为对象的一个​​字段.在这种情况下,您只获得方法,而不是名称和年龄变量.但是,如果您将 name 添加到列表中,那么您也可以执行 o.name.当然方法也是多方法;您可以为 getOlder 等添加多个定义,它会像您期望的那样工作.

It's weird that you have to return a function to do this, but there it is. This benefits from many optimizations like the language figuring out precise field types for you, so in some cases we can even inline these "method calls". Another cool feature is that the bottom line of the function controls which fields are "public"; anything listed there will become a field of the object. In this case you get only the methods, and not the name and age variables. But if you added name to the list then you'd be able to do o.name as well. And of course the methods are also multi-methods; you can add multiple definitions for getOlder etc. and it will work like you expect.

这篇关于如何创建一个“单一调度、面向对象的类"?在 julia 中,它的行为类似于具有公共/私有字段和方法的标准 Java 类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆