我需要一个类来调用包含它的类作为许多场景的属性 - 应该如何实现?

时间:2017-01-14 16:03:00

标签: ruby delegates structure

我是Ruby的新手,来自Objective-C和Swift。

我遇到了一个问题,我有一个包含另一个对象的对象作为属性。第二个对象具有beginStream函数,通过该函数从服务器流式传输数据,当它获取新数据时,它会产生,因此第一个对象可以响应。它看起来像这样:

class StreamManager
    def initialize
        @streams = Array.new
    end

    def setup_user_stream(user_id)
        stream = Stream.new(user_id)
        @streams << stream

        stream.begin_stream do |message|
            puts "A message was received: #{message}"
        end
    end
end

class Stream
    def initialize(user_id)
        @user_id = user_id
    end

    def begin_stream
        Thread.new do
            # Begins stream
            @client = Stream::Client.new(user_id)

            @client.on_error do
                # need to let StreamManager know about this
            end

            @client.on_message do |message|
                yield message if block_given?
            end
        end
    end
end

现在我从流客户端获得了这个on_error调用,我需要让我的StreamManager了解它。我该怎么做呢?

在Objective-C / Swift中,我有一个名为StreamDelegate的协议,该流将作为弱属性,然后StreamManager将Stream的委托设置为自身,并响应提供的功能。协议。因此,Stream将调用委托函数@delegate?.streamDidReceiveError,并将流管理器设置为delegate,并实现该函数,并将其调用。

我简化了这个例子 - Stream是Stream :: Client的抽象,它来自另一个库,并且还提供了许多其他消息。但是现在我正在写这篇文章,我想也许他们让我正在招揽那些不同的方块的方式就是要走的路。在这种情况下,我需要了解如何自己实现?或许这可能是设计我的班级的一种糟糕方式 - 我不知道?

2 个答案:

答案 0 :(得分:1)

StreamManager可以将自身作为变量传递给子Stream

def initialize(stream_manager, user_id)
    @stream_manager = stream_manager
    @user_id = user_id
end

并在setup_user_stream中初始化它:

stream = Stream.new(self, user_id)

如果您想要稍微冗长的代码,可以使用命名关键字:

def initialize(:stream_manager, :user_id)

然后:

Stream.new(stream_manager: self, user_id: user_id)

答案 1 :(得分:1)

这里有几种不同的方法:

1)你仍然可以使用你在Cocoa中习惯的委托模式。唯一的区别是你没有正式的协议/接口。您的Stream将采用委托/回调处理程序对象,该对象是实现某些方法的任何对象。您可以通过在调用它们之前检查对象是否响应它们来使这些方法成为可选方法。您的StreamManager可以实现此接口并将其作为依赖项传递给流。

2)您可以在Stream类上定义错误和消息的回调,而不是将单个块传递给begin_stream方法。

3)保留现有的API,而不是产生消息,将消息或错误封装在Result对象中,然后生成它。我想这可能是我的首选。

很抱歉缺少代码示例,但我在iPhone上写这个。