Sự khác biệt giữa các lĩnh vực và tài sản trong Julia là gì?


23

Julia có các chức năng setter setproperty!setfield!và các chức năng getter getpropertygetfieldhoạt động trên cấu trúc. Sự khác biệt giữa các tài sản và các lĩnh vực trong Julia là gì?

Ví dụ, những điều sau đây dường như chỉ ra rằng họ làm điều tương tự:

julia> mutable struct S
           a
       end

julia> s = S(2)
S(2)

julia> getfield(s, :a)
2

julia> getproperty(s, :a)
2

julia> setfield!(s, :a, 3)
3

julia> s
S(3)

julia> setproperty!(s, :a, 4)
4

julia> s
S(4)

Câu trả lời:


27

fieldschỉ đơn giản là "thành phần" của một cấu trúc. Cấu trúc

struct A
   b
   c::Int
end

có các lĩnh vực bc. Một cuộc gọi để getfieldtrả về đối tượng được liên kết với trường:

julia> a = A("foo", 3)
A("foo", 3)

julia> getfield(a, :b)
"foo"

Trong các phiên bản đầu của Julia, cú pháp a.bđược sử dụng để "hạ thấp", nghĩa là giống như cách viết getfield(a, :b). Điều đã thay đổi bây giờ là a.bgiảm xuống getproperty(a, :b)với dự phòng mặc định

getproperty(a::Type, v::Symbol) = getfield(a, v)

Vì vậy, theo mặc định, không có gì thay đổi. Tuy nhiên, các tác giả của cấu trúc có thể quá tải getproperty(không thể quá tải getfield) để cung cấp chức năng bổ sung cho cú pháp dấu chấm:

julia> function Base.getproperty(a::A, v::Symbol)
           if v == :c
               return getfield(a, :c) * 2
           elseif v == :q
               return "q"
           else
               return getfield(a, v)
           end
       end

julia> a.q
"q"

julia> getfield(a, :q)
ERROR: type A has no field q

julia> a.c
6

julia> getfield(a, :c)
3

julia> a.b
"foo"

Vì vậy, chúng tôi có thể thêm chức năng bổ sung cho cú pháp dấu chấm (động nếu chúng tôi muốn). Như một ví dụ cụ thể, nơi điều này hữu ích cho gói PyCall.jl nơi bạn đã từng phải viết pyobject[:field] trong khi bây giờ có thể thực hiện nó để bạn có thể viếtpyobject.field.

Sự khác biệt giữa setfield!setproperty!tương tự như sự khác biệt giữa getfieldgetproperty, được giải thích ở trên.

Ngoài ra, có thể nối vào hàm Base.propertynamesđể cung cấp tab hoàn thành các thuộc tính trong REPL. Theo mặc định, chỉ tên trường sẽ được hiển thị:

julia> a.<TAB><TAB>
b c

Nhưng bằng cách quá tải, propertynameschúng ta có thể làm cho nó cũng hiển thị các thuộc tính bổ sung q:

julia> Base.propertynames(::A) = (:b, :c, :q)

julia> a.<TAB><TAB>
b c q

Vì vậy, bạn không thể quá tải getfield?
Alfaizkhan

3
Không, getfieldlà một chức năng (tích hợp) đặc biệt. Cố gắng quá tải nó sẽ cho lỗi cannot add methods to a builtin function.
Kristoffer Carlsson

Có thể thêm thông tin đó vào câu trả lời ở đâu đó?
StefanKarpinki

2
Câu trả lời đã nói rõ ràng "(không thể quá tải getfield)" vì vậy, theo một nghĩa nào đó, nó đã có sẵn.
Kristoffer Carlsson
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.