2010-02-19 52 views
13

Làm cách nào để bạn truy cập một biến mẫu trong một phương thức mixin? Tôi có thể nghĩ ra 2 cách, nhưng cả hai dường như có vấn đề.Làm cách nào để bạn truy cập một biến mẫu trong một phương thức mixin?

  1. Phương pháp kết hợp truy cập biến mẫu trực tiếp như bất kỳ phương pháp lớp nào, ví dụ: self.text. Vấn đề với điều này là nó đặt những hạn chế về nơi mà phương pháp mixin có thể được sử dụng, và buộc các lớp làm việc trộn để có một phương pháp cụ thể được đặt tên theo một cách cụ thể.

  2. Vượt qua biến Ví dụ như một tham số cho phương thức mixin, mà sẽ cho kết quả trong mã như thế này:

dụ

self.do_something(self.text) 

hoặc

@thing.do_something(@thing.text) 

trông khó chịu với tôi, và không phù hợp với các nguyên tắc định hướng đối tượng.

Có cách nào khác để làm điều đó không ?, Tôi có được quan tâm không?

Trả lời

21

này Nhìn chung , tránh việc mixins truy cập vào các biến thành viên: Đó là một dạng khớp nối rất chặt chẽ có thể làm cho việc tái cấu trúc trong tương lai trở nên khó khăn một cách không cần thiết.

Một chiến lược hữu ích là Mixin luôn truy cập các biến thông qua người truy cập. Vì vậy, thay vì:

#!/usr/bin/ruby1.8 

module Mixin 

    def do_something 
    p @text 
    end 

end 

class Foo 

    include Mixin 

    def initialize 
    @text = 'foo' 
    end 

end 

Foo.new.do_something  # => "foo" 

các mixin truy cập vào "văn bản" accessor, mà được xác định bởi kể cả lớp:

module Mixin 

    def do_something 
    p text 
    end 

end 

class Foo 

    attr_accessor :text 

    include Mixin 

    def initialize 
    @text = 'foo' 
    end 

end 

Foo.new.do_something  # => "foo" 

gì nếu bạn cần bao gồm các Mixin trong lớp này?

class Foo 

def initialize 
    @text = "Text that has nothing to do with the mixin" 
end 

end 

Sử dụng tên dữ liệu chung và chung trong hỗn hợp có thể dẫn đến xung đột khi lớp bao gồm sử dụng cùng một tên.Trong trường hợp đó, có cái nhìn mixin cho dữ liệu với một tên ít phổ biến:

module Mixin 

    def do_something 
    p mixin_text 
    end 

end 

và để bao gồm cả lớp xác định accessor thích hợp:

class Foo 

    include Mixin 

    def initialize 
    @text = 'text that has nothing to do with the mixin' 
    @something = 'text for the mixin' 
    end 

    def mixin_text 
    @something 
    end 

end 

Foo.new.do_something  # => "text for the mixin" 

Bằng cách này, các accessor đóng vai trò như loại "trình kết hợp trở kháng" hoặc "trình dịch" giữa dữ liệu của kết hợp và dữ liệu của lớp bao gồm.

+0

Cảm ơn Wayne, bạn thực sự đã xóa nó. – dangerousdave

1

Bạn có thể cung cấp phương pháp dụ này mình trong mô-đun này, nhưng bạn phải cẩn thận không để ghi đè lên phương pháp hiện

Ví dụ (trong mô-đun bạn đang trộn trong):

def text 
    @text ||= "" 
end 
+1

Cảm ơn Kylo, ​​nhưng điều này vẫn có vẻ hạn chế cách mixin có thể được sử dụng. Lớp kéo nó trong vẫn phải có một biến cá thể @text. – dangerousdave

2

Instance tên biến bắt đầu bằng ruby ​​với một ví dụ @. @variable. Bạn có thể acces họ với tên này từ một Module bạn bao gồm

module M 
    def t 
    @t 
    end 
end 

class A 
    include M 
    def initialize(t) 
    @t= t 
    end 
end 

A.new(23).t # => 23 

Nếu bạn wan't để truy cập @t khi nó không được định nghĩa trong lớp học của bạn trước khi bạn có thể làm theo cách

module M 
    def t 
    instance_variable_defined?("@t") ? @t : nil 
    end 
end 
Các vấn đề liên quan