可变的Julia结构体中是否可能存在静态变量?

4
我希望能够在Julia结构体中定义静态变量。例如,我想定义以下内容:
```julia struct MyStruct static_var::Int = 0 end ```
mutable struct MyStruct
  global const a = 1
  b = 2
end

我希望能够以类似于Java或C ++语言中静态常量的方式访问a,例如:

MyStruct.a

我非常清楚这种编写代码的方式并不是朱利安(Julian)式的,我也可以使用一个模块来实现这个目的。

然而,我对于可变结构体是否能够实现此目的感兴趣。例如,我对于为什么不可能以及如何模拟这种编程模式的细节感兴趣。


正如我在我的回答中所说,Julia不允许您模拟这种OOP模式的原因是它是OOP的不幸结果。静态变量并不自然地属于结构体,那么为什么要把它们放在那里呢? - Oscar Smith
正如我在问题中所述,这不是关于正确编写Julia的方式,而是类似于https://dev59.com/PVkT5IYBdhLWcg3wD7Zb,但更加专业化。关于它们是否属于结构体,这在某种程度上取决于语言。例如,在C++中,我上面写的语法是允许的。 - JKRT
3个回答

3

(由于您要求不需要结构体实例,因此进行了编辑)

另一种方法是:

Original Answer翻译成"最初的回答"

julia> mutable struct MyStruct b::Int end

julia> a(::Type{MyStruct}) = 1
a (generic function with 1 method)

julia> a(MyStruct)
1

这需要再创建一个结构体,语法变为x.a.a,而不是x.a:

============================================================ 最初的回答:

你需要再创建一个结构体,然后访问时使用x.a.a而不是x.a:

julia> struct A
   a::Int
   end

julia> A() = A(1)
A

julia> s = A()
A(1)

julia> s.a
1

julia> mutable struct MyStruct
   a::A
   b::Int
   end

julia> MyStruct(b) = MyStruct(A(), b)
MyStruct

julia> c = MyStruct(3)
MyStruct(A(1), 3)

julia> c.a.a
1

julia> c.a.a = 5
ERROR: type A is immutable

我理解你这样做可以得到相同的行为(常量共享)。如果想要获得与Java/C ++中类似的语法,我们需要定义一个宏,因为没有语法糖。 - JKRT
通常情况下,类不需要静态变量。您可以通过使用一个函数来获取类似的行为,该函数接受一个结构实例,例如 static_a(::MyStruct) = 1; 而无需在结构中添加额外的插槽。但是,如果您需要模仿另一种语言的语法,那么可能需要使用宏来实现模仿语法。 - Bill
更新后的示例的问题在于,静态值与实际字段b之间没有关联,对吧? - JKRT

1

不确定您确切想要什么,但是

mutable struct MyStruct end

Base.getproperty(s::MyStruct, sym::Symbol) = (sym==:a ? 1 : getfield(s, sym))

julia> m = MyStruct()

julia> m.a
1

julia> m.a = 2
ERROR: type MyStruct has no field a
Stacktrace:
 [1] setproperty!(::MyStruct, ::Symbol, ::Int64) at ./Base.jl:21
 [2] top-level scope at REPL[18]:1

或者您可以输入MyStruct().a来执行。

您还可以重载setproperty!以提供更多信息的错误消息。


这样更整洁,不需要额外的结构体,因为有getProperty重载。但是,每次访问静态成员时仍需要创建对象吗? - JKRT
是的,它确实如此。Julia没有可以像这样行为的类。也许有其他方法,但我认为不会使用类型。 - DNF

0

我认为你实际上正在寻找的答案是一个结构体外的const变量。面向对象编程语言中存在静态变量的原因是有时您需要一个与类的实例无关的变量。在Julia中,您可以通过使用变量来实现这一点。

const a = 1
mutable struct Mystruct
    b::Int
end

将提供您想要的功能。它看起来不会面向对象,因为这不是 Julia 的设计方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接