Ruby on rails Ruby—;使用父级实例变量的子类

Ruby on rails Ruby—;使用父级实例变量的子类,ruby-on-rails,ruby,inheritance,Ruby On Rails,Ruby,Inheritance,您的代码引发错误: a1 = A.new('one') a2 = A.new('two') b1 = a1.B.new # not ruby syntax, but this is why I'm asking the question b2 = a2.B.new b3 = a2.B.new b3.test #=> 'two' b2.test #=> 'two' b1.test #=> 'one' B继承构造函数并在初始化中需要参数 见下文: b = B.new Argum

您的代码引发错误:

a1 = A.new('one')
a2 = A.new('two')
b1 = a1.B.new # not ruby syntax, but this is why I'm asking the question
b2 = a2.B.new
b3 = a2.B.new

b3.test
#=> 'two'
b2.test
#=> 'two'
b1.test
#=> 'one'
B
继承构造函数并在初始化中需要参数

见下文:

b = B.new
ArgumentError: wrong number of arguments (given 0, expected 1)
from (pry):14:in `initialize'
b=b.new(“你好”)
# => #
b、 试验
#你好
#=>零
如您所见,ivar是继承的

编辑

在这种情况下,最好使用组合而不是继承:

b = B.new("hello")
# => #<B:0x0000555b8b8c20d0 @var="hello">
b.test
# hello
# => nil
A类
def初始化(var)
@var=var
结束
属性存取器:var
结束
B类< /代码> 您可能想考虑一个类变量:

class A
  def initialize(var)
    @var = var
  end
  attr_accessor :var
end

class B < A
  def initialize(a)
    @a = a
  end

  def test
    puts var
  end

  def var
    a.var
  end

  def var=(var)
    a.var=(var)
  end
end

# or with delegation
class C < A
  def initialize(a)
    @a = a
  end
  delegate :var, :var=, to: :a

  def test
    puts var
  end
end
A类
def初始化(var)
@@var=var
结束
结束
B类“你好”

不可能像您所描述的那样使用“继承”,因为Ruby世界中没有从实例继承的东西。但是,话虽如此,您可以使用
委托
(您可以这样做,因为正如您所写的,您使用的是Rails),进行一些黑客操作,以实际获得(我猜)您需要的内容:

A类
attr_reader:var#在这里,您将方法设置为获取`@var`值
# ...
结束
B类

请记住,这是一个从头开始编写的解决方案,因为没有“同步”的方法来做到这一点,因为在Ruby世界中没有实例继承

实现目标的一个快捷方法是使用鲜为人知的类:

A类
属性读取器:var
def初始化(var)
@var=var
结束
结束
需要“委托人”
B类“两个”
b2.测试
#=>“两个”
b1.测试
#=>“一个”

这(“将您的工作转发到Ruby中的其他对象的5种方法”)可能会引起您的兴趣。

实现这一点的一种非常不受推荐的方法是将继承链移动到动态模块中,例如

class A
  attr_reader :var

  def initialize(var)
    @var = var
  end
end

require 'delegate'

class B < SimpleDelegator
  def test
    puts var
  end
end

a1 = A.new('one')
a2 = A.new('two')
b1 = B.new(a1)
b1 = B.new(a1)
b2 = B.new(a2)
b3 = B.new(a2)

b3.test
#=> 'two'
b2.test
#=> 'two'
b1.test
#=> 'one'
类可继承状态a,b,c=a.new,a.new,a.new
=> [#, #, #]
>a.扩展(InheritableState.new(“abc”));b、 扩展(InheritableState.new(“abc”));c、 扩展(InheritableState.new(“def”);
=> #
>[a.州,b.州,c.州]
=>[零,零,零]
>a.state=“abc”
=>“abc”
>[a.州,b.州,c.州]
=>[“abc”,“abc”,无]

对,我刚刚更新了代码示例。撇开bug不谈,问题是我是否可以让一个对象作为其父类实例的子对象来访问数据?为什么要这样做?你想让所有的
B
实例都从某个特定的
A
实例继承数据吗?我试图实现一种对象关系,在这种关系中,我可以在编辑后访问父对象的数据和方法:它不起作用,因为实例变量以某种方式“未共享”(无论它意味着什么),但因为您在
类中重写了方法
initialize
,所以现在它没有设置
@var
实例变量。你想达到什么目标?您试图获取“家长数据”是什么意思?实例变量只存在于实例上,而不存在于类上(它们确实存在,但情况不同)。当变量
@var
b
的上下文中更新时会发生什么?那么,
a.test
也应该改变吗?不清楚为什么要这样做——这不是Ruby(以及大多数其他OOP语言)中OOP的工作方式。听起来你想要一个“经典”和原型继承的混合体。虽然存在各种各样的黑客攻击,但最好将问题与语言相适应。@Mirror318这并不能真正解释为什么要这样做。到目前为止,听起来简单的组合更像是你想要的,或者是
a
的工厂。这是正确的方向,但我正在寻找一个范围为
a
实例的变量。因此,如果存在
a1=A.new('one')
a2=A.new('two')
,则
a1
的所有子类将看到
@var='one'
,而
a2
的所有子类将看到
@var='two'
类继承自类。但是
a1
a2
都是实例。不能从实例继承类。这很好。一个问题是,它将只从父类中委托公共方法(因此它不能执行例如私有的备忘录化方法)。你知道有什么办法吗?
class A
  def initialize(var)
    @@var = var
  end
end

class B < A
  def initialize
  end

  def test
    puts @@var
  end
end

a = A.new('hello')

b = B.new
b.test
#=> 'hello'
class A
  attr_reader :var # here, you set method to get `@var` value
  # ...
end

class B < A
  delegate :var, to: :a # here, you're setting delegator

  attr_reader :a # It's used by line above

  def initialize(a)
    @a = a
  end

  def test
    puts var
  end
end
a1 = A.new('one')
a2 = A.new('two')
b1 = B.new(a1)
b2 = B.new(a2)
b3 = B.new(a2)
b1.test
# one
b2.test
# two
b3.test
# two
class A
  attr_reader :var

  def initialize(var)
    @var = var
  end
end

require 'delegate'

class B < SimpleDelegator
  def test
    puts var
  end
end

a1 = A.new('one')
a2 = A.new('two')
b1 = B.new(a1)
b1 = B.new(a1)
b2 = B.new(a2)
b3 = B.new(a2)

b3.test
#=> 'two'
b2.test
#=> 'two'
b1.test
#=> 'one'
class InheritableState < Module
  def initialize(key)
    var_name = "@@#{key}_state".to_sym

    define_method :state do 
      return self.class.class_variable_get(var_name) if self.class.class_variable_defined?(var_name)
      self.class.class_variable_set(var_name, nil)
    end

    define_method :state= do |val|
      self.class.class_variable_set(var_name, val)
    end
  end
end

class A
end

> a, b, c = A.new, A.new, A.new
 => [#<A:0x00007fb691944338>, #<A:0x00007fb691944310>, #<A:0x00007fb6919442e8>]
> a.extend(InheritableState.new("abc")); b.extend(InheritableState.new("abc")); c.extend(InheritableState.new("def"));
 => #<A:0x00007fb6919442e8>
> [a.state, b.state, c.state]
 => [nil, nil, nil]
> a.state = "abc"
 => "abc"
> [a.state, b.state, c.state]
 => ["abc", "abc", nil]