2012-06-09 16 views

Trả lời

33

Khám phá các chung để chúng ta biết những gì chúng ta đang hướng tới

> getGeneric("[") 
standardGeneric for "[" defined from package "base" 

function (x, i, j, ..., drop = TRUE) 
standardGeneric("[", .Primitive("[")) 
<bytecode: 0x32e25c8> 
<environment: 0x32d7a50> 
Methods may be defined for arguments: x, i, j, drop 
Use showMethods("[") for currently available ones. 

Định nghĩa một lớp đơn giản

setClass("A", representation=representation(slt="numeric")) 

và thực hiện một phương pháp

setMethod("[", c("A", "integer", "missing", "ANY"), 
    ## we won't support subsetting on j; dispatching on 'drop' doesn't 
    ## make sense (to me), so in rebellion we'll quietly ignore it. 
    function(x, i, j, ..., drop=TRUE) 
{ 
    ## less clever: update slot, return instance 
    ## [email protected] = [email protected][i] 
    ## x 
    ## clever: by default initialize is a copy constructor, too 
    initialize(x, [email protected][i]) 
}) 

Trong hành động:

> a = new("A", slt=1:5) 
> a[3:1] 
An object of class "A" 
Slot "slt": 
[1] 3 2 1 

Có nhiều chiến lược khác nhau để hỗ trợ nhiều chữ ký (ngầm), ví dụ bạn có thể cũng muốn hỗ trợ các giá trị chỉ mục ký tự và logic, có thể cho cả i và j. Hướng thẳng đứng nhất là một mẫu "mặt tiền", trong đó mỗi phương pháp thực hiện một số áp lực sơ bộ đối với một loại chỉ mục con chung, ví dụ, integer để cho phép sắp xếp lại và lặp lại các mục chỉ mục, sau đó sử dụng callGeneric để gọi một phương thức duy nhất điều đó làm công việc của lớp học.

Không có sự khác biệt về khái niệm cho [[, ngoài việc muốn tôn trọng ngữ nghĩa trả về nội dung thay vì một thể hiện khác của đối tượng như được ngụ ý bởi [. Đối với $ chúng tôi có

> getGeneric("$") 
standardGeneric for "$" defined from package "base" 

function (x, name) 
standardGeneric("$", .Primitive("$")) 
<bytecode: 0x31fce40> 
<environment: 0x31f12b8> 
Methods may be defined for arguments: x 
Use showMethods("$") for currently available ones. 

setMethod("$", "A", 
    function(x, name) 
{ 
    ## 'name' is a character(1) 
    slot(x, name) 
}) 

với

> a$slt 
[1] 1 2 3 4 5 
+7

Cảm ơn Martin! Điều này thực sự hữu ích (đến mức mà tôi vi phạm quy tắc "không để lại lời cảm ơn vì nó là tiếng ồn" :-) –

7

tôi sẽ làm như @Martin_Morgan gợi ý cho các nhà khai thác mà bạn đề cập. Tôi sẽ thêm một vài điểm mặc dù:

1) Tôi sẽ cẩn thận khi xác định toán tử $ để truy cập khe S4 (trừ khi bạn định truy cập cột từ khung dữ liệu được lưu trữ trong một vị trí cụ thể?) . Đề xuất chung là viết các hàm truy cập như getMySlot()setMySlot() để nhận thông tin bạn cần. Bạn có thể sử dụng toán tử @ để truy cập dữ liệu từ các vị trí đó, mặc dù nhận và đặt là giao diện người dùng tốt nhất. Sử dụng $ có thể gây nhầm lẫn cho người dùng, những người có thể mong đợi một data.frame. Xem bài hướng dẫn this S4 của Christophe Genolini để có một cuộc thảo luận chuyên sâu về những vấn đề này. Nếu đây không phải là cách bạn dự định sử dụng $, hãy bỏ qua đề xuất của tôi (nhưng hướng dẫn vẫn là tài nguyên tuyệt vời!).

2) Nếu bạn đang định [[[ kế thừa từ lớp khác, như vector, bạn cũng sẽ muốn xác định el() (tương đương với [][[1L]], hoặc các yếu tố đầu tiên từ một tập hợp con []) và length(). Tôi hiện đang viết một lớp để kế thừa từ số, và các phương thức số sẽ tự động cố gắng sử dụng các hàm này từ lớp của bạn. Nếu lớp học có hạn chế hơn hoặc sử dụng cá nhân của riêng bạn, điều này có thể không phải là một vấn đề.

Tôi xin lỗi, tôi đã để lại nhận xét này, nhưng tôi là người mới đối với SO và tôi chưa có đại diện!

Các vấn đề liên quan