Ruby: Наследуйте код, который работает с переменными класса

Согласно документам ( http://ca3.php.net/language.oop5.cloning ):

$a = clone $b;

42
задан MPelletier 22 June 2012 в 02:11
поделиться

1 ответ

@@ переменные не являются переменными класса. Они являются переменными иерархии классов , то есть они являются общими для всей иерархии классов, включая все подклассы и все экземпляры всех подклассов. (Было высказано предположение, что следует думать о @@ переменных больше как о $$ переменных , потому что они на самом деле имеют больше общего с $ globals , чем с @ivars . В этом случае меньше путаницы. Другие пошли еще дальше и предлагают просто удалить их из языка.)

Ruby не имеет переменных класса в том смысле, в котором, скажем, Java ( где они называются статическими полями) есть их. Ему не нужны переменные класса , потому что классы также являются объектами, и поэтому они могут иметь переменные экземпляра , как и любой другой объект. Все, что вам нужно сделать, это удалить лишние @ s. (И вам нужно будет предоставить метод доступа для переменной экземпляра класса.)

class A
  def self.init config
    @config = config
  end

  def self.config # This is needed for access from outside
    @config
  end

  def config
    self.class.config # this calls the above accessor on self's class
  end
end

Давайте немного упростим это, поскольку A.config явно является просто attribute_reader:

class A
  class << self
    def init config
      @config = config
    end

    attr_reader :config
  end

  def config
    self.class.config
  end
end

И, фактически, A.init - это просто писатель с забавным именем, поэтому давайте переименуем его в A.config = и сделаем писателем, что, в свою очередь, означает, что наша пара методов теперь просто пара аксессуаров. (Поскольку мы изменили API, очевидно, должен измениться и тестовый код.)

class A
  class << self
    attr_accessor :config
  end

  def config
    self.class.config
  end
end

class B < A; end
class C < A; end

B.config = "bar"
p B.new.config  # => "bar"
p C.new.config  # => nil

C.config = "foo"
p B.new.config  # => "bar"
p C.new.config  # => "foo"

Однако я не могу избавиться от ощущения, что в дизайне есть что-то более фундаментально сомнительное, если оно вам вообще нужно.

Все, что вам нужно сделать, это удалить лишние @ s. (И вам нужно будет предоставить метод доступа для переменной экземпляра класса.)

class A
  def self.init config
    @config = config
  end

  def self.config # This is needed for access from outside
    @config
  end

  def config
    self.class.config # this calls the above accessor on self's class
  end
end

Давайте немного упростим это, поскольку A.config явно является просто attribute_reader:

class A
  class << self
    def init config
      @config = config
    end

    attr_reader :config
  end

  def config
    self.class.config
  end
end

И, фактически, A.init - это просто писатель с забавным именем, поэтому давайте переименуем его в A.config = и сделаем его писателем, что, в свою очередь, означает, что наша пара методов теперь просто пара аксессуаров. (Поскольку мы изменили API, очевидно, должен измениться и тестовый код.)

class A
  class << self
    attr_accessor :config
  end

  def config
    self.class.config
  end
end

class B < A; end
class C < A; end

B.config = "bar"
p B.new.config  # => "bar"
p C.new.config  # => nil

C.config = "foo"
p B.new.config  # => "bar"
p C.new.config  # => "foo"

Однако я не могу избавиться от ощущения, что в дизайне есть что-то более принципиально сомнительное, если оно вам вообще нужно.

Все, что вам нужно сделать, это удалить лишние @ s. (И вам нужно будет предоставить метод доступа для переменной экземпляра класса.)

class A
  def self.init config
    @config = config
  end

  def self.config # This is needed for access from outside
    @config
  end

  def config
    self.class.config # this calls the above accessor on self's class
  end
end

Давайте немного упростим это, поскольку A.config явно является просто attribute_reader:

class A
  class << self
    def init config
      @config = config
    end

    attr_reader :config
  end

  def config
    self.class.config
  end
end

И, фактически, A.init - это просто писатель с забавным именем, поэтому давайте переименуем его в A.config = и сделаем его писателем, что, в свою очередь, означает, что наша пара методов теперь просто пара аксессуаров. (Поскольку мы изменили API, очевидно, должен измениться и тестовый код.)

class A
  class << self
    attr_accessor :config
  end

  def config
    self.class.config
  end
end

class B < A; end
class C < A; end

B.config = "bar"
p B.new.config  # => "bar"
p C.new.config  # => nil

C.config = "foo"
p B.new.config  # => "bar"
p C.new.config  # => "foo"

Однако я не могу избавиться от ощущения, что в дизайне есть что-то более фундаментально сомнительное, если оно вам вообще нужно.

)

class A
  def self.init config
    @config = config
  end

  def self.config # This is needed for access from outside
    @config
  end

  def config
    self.class.config # this calls the above accessor on self's class
  end
end

Давайте немного упростим это, поскольку A.config явно является просто attribute_reader:

class A
  class << self
    def init config
      @config = config
    end

    attr_reader :config
  end

  def config
    self.class.config
  end
end

И, по сути, A.init - это просто писатель с забавным name, поэтому давайте переименуем его в A.config = и сделаем его писателем, что, в свою очередь, означает, что наша пара методов теперь просто пара методов доступа. (Поскольку мы изменили API, очевидно, должен измениться и тестовый код.)

class A
  class << self
    attr_accessor :config
  end

  def config
    self.class.config
  end
end

class B < A; end
class C < A; end

B.config = "bar"
p B.new.config  # => "bar"
p C.new.config  # => nil

C.config = "foo"
p B.new.config  # => "bar"
p C.new.config  # => "foo"

Однако я не могу избавиться от ощущения, что в дизайне есть что-то более фундаментально сомнительное, если оно вам вообще нужно.

)

class A
  def self.init config
    @config = config
  end

  def self.config # This is needed for access from outside
    @config
  end

  def config
    self.class.config # this calls the above accessor on self's class
  end
end

Давайте немного упростим это, поскольку A.config явно является просто attribute_reader:

class A
  class << self
    def init config
      @config = config
    end

    attr_reader :config
  end

  def config
    self.class.config
  end
end

И, по сути, A.init - это просто писатель с забавным name, поэтому давайте переименуем его в A.config = и сделаем его писателем, что, в свою очередь, означает, что наша пара методов теперь является просто парой средств доступа. (Поскольку мы изменили API, очевидно, должен измениться и тестовый код.)

class A
  class << self
    attr_accessor :config
  end

  def config
    self.class.config
  end
end

class B < A; end
class C < A; end

B.config = "bar"
p B.new.config  # => "bar"
p C.new.config  # => nil

C.config = "foo"
p B.new.config  # => "bar"
p C.new.config  # => "foo"

Однако я не могу избавиться от ощущения, что в дизайне есть что-то более фундаментально сомнительное, если оно вам вообще нужно.

что, в свою очередь, означает, что наша пара методов теперь просто пара аксессоров. (Поскольку мы изменили API, очевидно, должен измениться и тестовый код.)

class A
  class << self
    attr_accessor :config
  end

  def config
    self.class.config
  end
end

class B < A; end
class C < A; end

B.config = "bar"
p B.new.config  # => "bar"
p C.new.config  # => nil

C.config = "foo"
p B.new.config  # => "bar"
p C.new.config  # => "foo"

Однако я не могу избавиться от ощущения, что в дизайне есть что-то более фундаментально сомнительное, если оно вам вообще нужно.

что, в свою очередь, означает, что наша пара методов теперь просто пара аксессоров. (Поскольку мы изменили API, очевидно, должен измениться и тестовый код.)

class A
  class << self
    attr_accessor :config
  end

  def config
    self.class.config
  end
end

class B < A; end
class C < A; end

B.config = "bar"
p B.new.config  # => "bar"
p C.new.config  # => nil

C.config = "foo"
p B.new.config  # => "bar"
p C.new.config  # => "foo"

Однако я не могу избавиться от ощущения, что в дизайне есть что-то более принципиально сомнительное, если оно вам вообще нужно.

109
ответ дан 26 November 2019 в 23:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: