Ruby - Использование параметров nil для поддержки различных типов классов - PullRequest
0 голосов
/ 22 февраля 2019

В Ruby, скажем, у меня есть класс с именем Song.Я хотел бы знать, как правильно написать initialize, чтобы он поддерживал 2 различных типа.Например:

song_full = Song.new(fromSomeCloudStorage)

song_preview = Song.new(fromLocalStorage)

Затем скажите, что у меня есть класс Song, где я всегда хочу назначить @time_stamp, но затем в зависимости отесть ли cloud_storage или нет, присвойте @cloud_store_spec

def initialize(cloud_storage = nil, time_stamp = nil, local_storage = nil)
    @time_stamp = time_stamp || (Time.now.to_f * 1000).to_i.to_s
    @cloud_store_spec = cloud_storage
end 

Я думаю об использовании nil, как я сделал, однако код знал бы, что является cloud_storage, а что является local_storage.Это действительно возможно?

Любая помощь приветствуется?

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

Если CloudStorage или LocalStorage можно рассматривать как классы:

class LocalStorage
  def initialize; p 'LocalStorage class initialized'; end
end

class CloudStorage
  def initialize; p 'CloudStorage class initialized'; end
  def play; p "...playing song"; end
end

Возможно, вы могли бы подумать о том, чтобы жестко закодировать Hash, (не говоря уже о time_stamp):

class Song
  attr_reader :store_spec

  def initialize(kind = nil)
    storage_kind = {cloud: CloudStorage, preview: LocalStorage}
    @store_spec = storage_kind[kind].new
  end

  def storage_kind
    @store_spec.class
  end

  def play
    @store_spec.play
  end
end

Так что вы можетепозвоните например:

song = Song.new(:cloud) #=> "CloudStorage class initialized"
song.storage_kind #=> CloudStorage
song.play #=> "...playing song"
0 голосов
/ 22 февраля 2019

Прежде всего, используйте аргументы ключевого слова, чтобы позволить вам передать соответствующие данные инициализатору (вплоть до вас, если вы хотите включить time_stamp в качестве ключевого слова или обычного аргумента):

def initialize(cloud_storage: nil, local_storage: nil, time_stamp: nil)
  @time_stamp = time_stamp || (Time.now.to_f * 1000).to_i.to_s
  @cloud_store_spec = cloud_storage
end

Этобудет намного понятнее при вызове класса, что позволит:

song_full = Song.new(cloud_storage: fromSomeCloudStorage)
song_preview = Song.new(local_storage: fromLocalStorage)

С точки зрения того, как ваш код будет знать, является ли код облачным или локальным, если вы имеете в виду экземпляры класса, вы можете просто проверитьдля присутствия @cloud_store_spec, что-то вроде:

def cloud_storage?
  @cloud_store_spec.present?
end

Затем, из любого места в вашем коде, вы можете позвонить:

song_full = Song.new(cloud_storage: fromSomeCloudStorage)
song_full.cloud_storage? # => true

song_preview = Song.new(local_storage: fromLocalStorage)
song_preview.cloud_storage? # => false

Надеюсь, что помогает, и я читаюВы правы :) Дайте мне знать, как вы ладите или если у вас есть какие-либо вопросы.


Обновление для Ruby 1.9.3

Поскольку аргументы ключевых слов былиПредставленный в Ruby 2.0, для 1.9.3 вы можете использовать хэш опций:

def initialize(options = {}) # again, timestamp can be a separate arg if you'd prefer
  @time_stamp = options[:time_stamp] || (Time.now.to_f * 1000).to_i.to_s
  @cloud_store_spec = options[:cloud_storage]
end

Остальная часть кода останется прежней.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...