简体   繁体   English

我应该如何在Ruby中定义其处理算法在超类中定义的实例变量?

[英]How should I define an instance variable in Ruby whose processing algorithm is defined in a super class?

In short: I want to define the algorithm in the superclass which inherits into all subclasses, but I want to define the data (on which the algorithm operates) in the subclasses as instance variables, which come into being when I call the "new" method of the given classes. 简而言之:我想在继承到所有子类的超类中定义算法,但是我想在子类中将数据(算法在其上进行操作)定义为实例变量,这些实例变量是在我调用“ new”时产生的给定类的方法。 What is the standard way for doing this in Ruby? 在Ruby中执行此操作的标准方法是什么?

My solution is (but I am not exactly sure this is the right way): 我的解决方案是(但是我不确定这是正确的方法):

class A
   attr_accessor :var
   def initialize
     @var=nil #I dont know the actual value, it will be defined only in the more specific subclasses.
   end

   def process_data
      puts @var #simply puts it out
   end
end

#in my program all further classes are inherited form class A, the processing facility is inherited, only the data varies.

class B < A
   attr_accessor :var
   def initialize
     @var=10 #specific value for class B which is always 10, no need for example b=B.new(20)
   end
end

class C < A
   attr_accessor :var
   def initialize
     @var=20 #specific value for class C which is always 20, no need for example c=C.new(20)
   end
end

b=B.new
b.process_data #needs to print 10

c=C.new
c.process_data #needs to print 20

What you have works. 您所拥有的作品。 There's just some unneeded stuff in there: 那里只有一些不需要的东西:

Instance variables evaluate to nil if they are uninitialized and they spring into existence as soon as they are used, so your A#initialize method is unnecessary. 如果实例变量未初始化,则其求值为nil ,并且一旦使用它们便会立即存在,因此不需要A#initialize方法。

You override the A#var and A#var= methods in B and C with methods that do the exact same thing. 使用执行完全相同的操作的方法覆盖BCA#varA#var=方法。 There is no need for that, just get rid of the calls to attr_accessor in the definition of B and C . 不需attr_accessor ,只需摆脱BC定义中对attr_accessor的调用。

You create var and var= accessor methods but you never use them. 您创建了varvar=访问器方法,但从未使用过它们。 Either get rid of the call to attr_accessor or (preferably) use the accessor methods, ie use self.var = in initialize and puts var in process_data . 摆脱对attr_accessor的调用,或者(最好)使用accessor方法,即在initialize使用self.var = puts var放入process_data

class A
  attr_accessor :var

  def process_data
    puts var #simply puts it out
  end
end

#in my program all further classes are inherited form class A, the processing facility is inherited, only the data varies.

class B < A
  def initialize
    self.var = 10 #specific value for class B which is always 10, no need for example b=B.new(20)
  end
end

class C < A
  def initialize
    self.var = 20 #specific value for class C which is always 20, no need for example c=C.new(20)
  end
end

b = B.new
b.process_data #needs to print 10

c = C.new
c.process_data #needs to print 20

[Note: your coding style was also off. [注意:您的编码风格也已关闭。 Indentation is 2 spaces in Ruby, not 3.] 缩进在Ruby中为2个空格,而不是3个空格。]

However, if the value of @var is always the same for all instances of B , then why do you need multiple instances of B ? 但是,如果对于B所有实例,@ @var的值始终相同,那么为什么需要多个B实例?

Why not something like this: 为什么不这样:

class A
  attr_accessor :var

  def initialize(val)
    self.var = val
  end

  def process_data
    puts var #simply puts it out
  end
end

b = A.new(10)
b.process_data #needs to print 10

c = A.new(20)
c.process_data #needs to print 20

You are doing it in almost the right way. 您正在以几乎正确的方式进行操作。 A minor point is that your A::initialize definition is redundant for two reasons: 还有一点要注意的是,您的A::initialize定义是多余的,原因有两个:

  • An instance variable is initialized to nil automatically. 实例变量自动初始化为nil
  • The initialize methods in the subclasses will override A::initialize when the subclass instances are created. 创建子类实例时,子类中的initialize方法将覆盖A::initialize

Also, the attr_accessor calls in the subclasses are redundant. 同样,子类中的attr_accessor调用是多余的。


Now I seem to get what you wanted. 现在我似乎得到了您想要的。 You can use class-level instance variables. 您可以使用类级别的实例变量。

class A
  def initialize
    @var=self.class.instance_variable_get(:@var)
  end
  def process_data
    puts @var
  end
end

class B < A
  @var = 10
end

class C < A
  @var = 20
end

B.new.process_data # => 10
C.new.process_data # => 20

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM