อะไรคือความแตกต่างระหว่างฟิลด์และคุณสมบัติในจูเลีย?


23

Julia มีฟังก์ชั่น setter setproperty!และsetfield!และ getter function getpropertyและgetfieldทำงานบน structs ความแตกต่างระหว่างคุณสมบัติและเขตข้อมูลใน Julia คืออะไร?

ตัวอย่างเช่นต่อไปนี้ดูเหมือนจะบ่งบอกว่าพวกเขาทำสิ่งเดียวกัน:

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)

คำตอบ:


27

fieldsเป็นเพียง "ส่วนประกอบ" ของโครงสร้าง โครงสร้าง

struct A
   b
   c::Int
end

มีทุ่งนาและb cการเรียกเพื่อgetfieldส่งคืนวัตถุที่ถูกผูกไว้กับเขตข้อมูล:

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

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

ในรุ่นแรกของจูเลียไวยากรณ์a.bที่ใช้ในการ "ลด" getfield(a, :b)คือเป็นเช่นเดียวกับการเขียน สิ่งที่เปลี่ยนแปลงไปในขณะนี้คือการ a.bลดลงgetproperty(a, :b)เมื่อเลือกทางเลือกเริ่มต้น

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

ดังนั้นโดยค่าเริ่มต้นไม่มีอะไรเปลี่ยนแปลง อย่างไรก็ตามผู้เขียน structs สามารถโอเวอร์โหลดgetproperty(เป็นไปไม่ได้ที่จะโอเวอร์โหลดgetfield) เพื่อจัดเตรียมฟังก์ชันการทำงานเพิ่มเติมให้กับไวยากรณ์จุด:

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"

ดังนั้นเราสามารถเพิ่มฟังก์ชั่นพิเศษให้กับไวยากรณ์จุด (แบบไดนามิกถ้าเราต้องการ) เป็นตัวอย่างที่เป็นประโยชน์ที่มีประโยชน์สำหรับแพ็คเกจ PyCall.jl ที่คุณเคยต้องเขียนpyobject[:field] ในขณะที่มันเป็นไปได้ที่จะนำไปใช้ในขณะนี้เพื่อให้คุณสามารถเขียนpyobject.field.

ความแตกต่างระหว่างsetfield!และsetproperty!คล้ายคลึงกับความแตกต่างระหว่างgetfieldและgetpropertyอธิบายข้างต้น

นอกจากนี้ยังเป็นไปได้ที่จะขอให้เข้าไปในฟังก์ชั่นBase.propertynamesเพื่อจัดทำคุณสมบัติของแท็บให้สมบูรณ์ใน REPL ตามค่าเริ่มต้นเฉพาะชื่อฟิลด์เท่านั้นที่จะแสดง:

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

แต่ด้วยการบรรทุกเกินพิกัดpropertynamesเราสามารถทำให้มันแสดงทรัพย์สินพิเศษได้อีกด้วยq:

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

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

ดังนั้นคุณไม่สามารถโหลดเกินพิกัด
Alfaizkhan

3
ไม่getfieldเป็นฟังก์ชั่นพิเศษ (ในตัว) cannot add methods to a builtin functionพยายามที่จะเกินก็จะให้ข้อผิดพลาด
Kristoffer Carlsson

อาจเพิ่มข้อมูลนั้นในคำตอบที่ไหนสักแห่ง?
StefanKarpinski

2
คำตอบนั้นบอกอย่างชัดเจนว่า "(มันเป็นไปไม่ได้ที่จะโอเวอร์โหลดgetfield)" ดังนั้นในแง่หนึ่งก็มีอยู่แล้ว
Kristoffer Carlsson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.