2015-02-25 15 views
11

Tôi đang cố gắng sử dụng bộ tổng hợp truy cập trên một thành phần trên Lucee (mặc dù vấn đề này dường như giống nhau trên Coldfusion quá).Hành vi không mong muốn với accessors = true trên một thành phần

đang

Repro:

// Person.cfc 
component accessors=true { 

    property firstName; 
    property lastName; 

    function init(firstName, lastName){ 
     variables.firstName = arguments.firstName; 
     variables.lastName = arguments.lastName; 
    } 

} 

Và mã gọi:

// person.cfm 
person = new Person("Abigail", "Bowen"); 
writeDump(person); 

Chú ý cách tôi không sử dụng accessors tổng hợp ở đây, tôi hoàn toàn thiết lập các giá trị đối số vào cùng tên biến biến có phạm vi biến.

Tuy nhiên khi tôi chạy mã này, tôi thấy điều này:

Dump output showing properties

Lưu ý cách các thuộc tính đã được dân cư. Không có vấn đề với điều này, nhưng tôi rõ ràng không hiểu làm thế nào cờ accessors là nghĩa vụ phải làm việc. Tôi nghĩ rằng nó chỉ đơn thuần là nhằm tổng hợp một số phương pháp truy cập cho tôi (mà nó có), nhưng đó là tất cả.

Cũng lưu ý rằng nếu tôi sửa đổi định nghĩa CFC để không bộ accessors true, sau đó bãi cho thấy điều này:

Dump with no properties

Vì vậy, không accessors tổng hợp (như mong đợi), mà còn bây giờ là các thuộc tính thậm chí không được hiển thị (với các giá trị biến có phạm vi hay không).

Tôi không thực sự hiểu được sự nhầm lẫn này của "thuộc tính" và cài đặt trình truy cập? Chắc chắn các thiết lập accessors chỉ nên tác động cho dù những phương thức accessor được tạo ra?

Nếu tôi chỉ nhìn thấy điều này trên một trong các nền tảng, tôi có thể đặt nó xuống một cách mơ hồ về cách writeDump() diễn giải định nghĩa thuộc tính. Nhưng hành vi là như nhau trên ColdFusion 11, vì vậy nó thực sự có vẻ như có một số khác biệt trong hành vi tôi không hoàn toàn nhận được.

Có ai có thể giải thích điều này không? Có bất kỳ tài liệu nào giải thích nó không? Nếu không ... um ... tại sao không?

Mối quan tâm cơ bản của tôi ở đây là giá trị thuộc tính không được lưu trữ "đúng" và có thể gây ra sự cố cho tôi khi tôi triển khai thêm mã.

CẬP NHẬT: Ít nhất trên ColdFusion, có vẻ như chỉ là một thay đổi trong hành vi của writeDump(), bởi vì nếu có getters cho các thuộc tính (có hoặc không đặt cờ accessors) thì giá trị thuộc tính bắt đầu hiển thị trong bãi chứa. Đây không phải là trường hợp của Lucee, vì vậy vẫn còn một dấu hỏi ở đó.

Để được tiết lộ đầy đủ, câu hỏi này là bản tóm tắt câu hỏi tôi cũng đã hỏi trên blog của mình ("CFML: trying to understand accessors"). Sự trùng lặp là cố ý vì blog của tôi thu hút được nhiều đối tượng khác nhau từ trang web này.

Trả lời

10

Nếu không có accessors=true, khai báo property chỉ là siêu dữ liệu.

Với accessors=true, các property tờ khai kích hoạt việc tạo ra getters/setters và do đó một property vừa là mục variables phạm vi một cặp phương pháp. Trong các nhà xây dựng của bạn, bạn gán cho các mặt hàng phạm vi variables - sẽ giống như sử dụng các bộ tạo được tạo - và khi CFML kết xuất thành phần, nó sẽ thấy siêu dữ liệu property và các getters được tạo ra và do đó nó hiển thị các giá trị mà các thuộc tính đó có (vì nó có thể gọi các getters được tạo ra một cách dễ dàng và an toàn).

+1

Vâng, điều này có vẻ không rõ (xem bản cập nhật của tôi). Hành vi của Lucee hơi có mâu thuẫn với ColdFusion ở đây. Tôi đoán Lucee tìm kiếm thiết lập * và * các phương pháp; CF chỉ tìm kiếm các phương pháp. Và sự khác biệt hoàn toàn nằm trong hành vi đổ rác, không phải bất cứ thứ gì khác. –

+0

Đây có phải là trường hợp hoạt động của hàm tạo CF9 không? Trong CF9, init() đã trở thành một hàm tạo đúng trong đó nếu bạn có một, nó được tự động gọi khi bạn sử dụng từ khóa mới, giống như trong Java. Điều tương tự cũng xảy ra nếu bạn đổi tên init() thành Person(). Nếu các bạn là chính xác, nó cũng sẽ xảy ra nếu bạn sử dụng một số tên hàm khác - mà nó không có. Nó chỉ xảy ra khi CF đang chạy như một hàm tạo. – ialexander

2

Điều này xuất hiện với ACF9. Cho đến lúc đó định nghĩa trong tài liệu thuộc tính là đúng: khai báo cfproperty là chỉ siêu dữ liệu. (Xem bãi (getMetaData())

Trong ACF9 này là không hoàn toàn đúng nữa cho 3 lý do:.

  1. Với accessors=true một getter và setter được tạo ra cho mỗi tài sản và những accessors đọc từ và ghi Cfproperty không chỉ là siêu dữ liệu nữa, mà còn ảnh hưởng trực tiếp đến hành vi của cá thể, tôi thích nghĩ về nó như là phiên bản CF của các thuộc tính OO thực (được giới thiệu một cách ngẫu nhiên)

  2. c fdump thực hiện thay đổi hành vi của nó dựa trên các khai báo thuộc tính. Nếu property name; được xác định và phương pháp getName() tồn tại (được tạo hoặc triển khai), nó sẽ được thêm vào phần thuộc tính của bãi chứa.

  3. Thuộc tính thuộc tính kiểm soát ORM.

Vì tôi biết các tính năng này, tôi thiết kế tất cả các CFC của tôi (công khai) để nhìn ngay khi được đổ, ví dụ: Tôi chỉ sử dụng khai báo tài sản (+ getters) khi tôi muốn hiển thị nó. Ngoài ra, bạn có thể thực hiện phương pháp mà chỉ được gọi bởi các bãi và chi phí không có gì trên instantiation:

struct function getDebug(){ 
    var x = doSomethingExpensive(); 
    return { "Foo":f, "Bar":b, "Baz":x }; 
} 

//or for a user iterator 
string function getName(){ 
    return qUsers.name[index]; 
} 

Một số hãy cẩn thận tôi biết:

  • ACF luôn gọi thu khí từ bãi, trong khi ở Railo/Lucee giá trị từ phạm vi biến được hiển thị. Do đó, các ví dụ trên (getDebug()getName()) không hoạt động trên Railo/Lucee.
  • Nếu trình thu thập không công khai hoặc dẫn đến lỗi, kết xuất hiển thị chuỗi trống cho thuộc tính (không chắc chắn ở đây, có thể thuộc tính bị thiếu thay thế).
  • Tuyên bố thuộc tính trong CFC mở rộng được bỏ qua. Điều này đã cho tôi một số nhức đầu trong các thực thể ORM sử dụng thừa kế, bởi vì bạn không được phép khai báo một thuộc tính hai lần. Do đó, bạn không có khả năng hiển thị một thuộc tính được định nghĩa trong một CFC cơ sở.
  • Railo/Lucee dường như bỏ qua các loại thuộc tính. Tất cả accessor chấp nhận và trả về các chuỗi chỉ (xem getMetaData()).
  • Nhỏ: Trong ACF khi bạn kích hoạt người truy cập, nhưng tắt getter và setter cho thuộc tính: property name="user" getter="false" setter="false"; nó vẫn hiển thị trong bãi chứa - nó sẽ bị ẩn.
Các vấn đề liên quan