2017-01-14 9 views
0

Я довольно новичок в 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 :: Client, который из другой библиотеки, а также выдает кучу других сообщений. Но теперь я пишу это, я думаю, что, возможно, их способ иметь те разные блоки, которые я уступаю, - это путь. В таком случае мне нужно будет понять, как реализовать это сам? Или, может быть, это будет плохой способ разработать мой класс - я не знаю?

ответ

1

Есть несколько разных pproaches здесь:

1) Вы все еще можете использовать шаблон делегата, к которому вы привыкли в Cocoa. Единственное различие заключается в том, что у вас не будет формального протокола/интерфейса для него. В вашем потоке будет объект-обработчик делегирования/обратного вызова, который является любым объектом, который реализует определенные методы. Вы можете сделать эти методы необязательными, проверяя, что объект отвечает на них перед их вызовом. Ваш StreamManager может реализовать этот интерфейс и передать себя потоку в качестве зависимости.

2) Вы можете определить обратные вызовы класса Stream для ошибок и сообщений, а не передавать один блок методу begin_stream.

3) Держите свой существующий API вместо того, чтобы давать сообщение, инкапсулируйте сообщение или ошибку в объект Result и получите это вместо этого. Я думаю, что это может быть моим предпочтительным вариантом.

Извините за отсутствие примеров кода, но я пишу это на своем iPhone.

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) 
+0

Пара вопросов ... Разве это не сделало бы диспетчер потоков сильно защищенным свойством потока?Есть ли способ, которым я могу иметь диспетчер потоков не обязательно из класса StreamManager, а просто для класса, который соответствует протоколу? Это будет уместно? Или это еще не вещь Руби? – Andrew

+0

Конечно, вместо этого вы можете написать класс-оболочку для менеджера и ссылку. Я бы не подумал об этом с точки зрения «это рубиновая вещь», потому что это действительно зависит от того, какие стандарты вы придерживаетесь в плане дизайна. Если класс менеджера является абстрактным, и вы хотите написать какой-то конкретный код для конкретного случая, во что бы то ни стало, сделайте обертку. Но в общем смысле я не вижу, где бугимен, если хранить ссылку на экземпляр отдельного класса. –

 Смежные вопросы

  • Нет связанных вопросов^_^