从子类访问实例变量

3

我正在尝试从子类访问父类的一个数据成员,但不确定如何调用它。我找到了很多关于如何从子类访问类变量而不是实例变量的信息。以下是我的代码:

class Shape

    @var = "woohoo"

    def initialize ()

    end

    def area ()

    end

end


class Rectangle < Shape

    @length
    @width

    def initialize ( l,w )
        @length = l
        @width = w
    end

    def area ()
      print @var
      return @length * @width
    end

end

我在尝试打印@var时遇到了错误。 我尝试了parent.@var,Shape.@var和其他许多我从其他语言中期望的组合。 在子类实例中打印(并且如果可能更改)该变量的正确方法是什么?
编辑:我希望子类的各个实例将“woohoo”字符串替换为它们自己的独特字符串。
谢谢!
2个回答

5

I'm trying to access a datamember of a parent class from a child class. I am not sure how to call it. I have found a lot of info about accessing class variables but not instance variables from a child class. Here is my code:

class Shape
  @var = "woohoo"

那个变量被称为类实例变量,人们使用类实例变量而不是类变量,即@@variable的原因,就是为了防止子类访问它。由于类实例变量是其他语言中类变量的工作方式,因此在ruby中不太使用@@variables,因为如果来自另一种具有类变量的语言,则其行为令人惊讶。

显然您的用例需要在子类中访问类变量,因此请使用@@variable

编辑:我希望子类的单个实例将“woohoo”字符串替换为它们自己的唯一字符串。

您可以使用类实例变量

class Shape
  @var = "shapehoo"

  class <<self
    attr_accessor :var
  end

  def display_class_instance_var
    puts Shape.var
  end

end

class Rectangle < Shape
  @var = "recthoo"

  def display_class_instance_var
    puts Rectangle.var
  end
end

class Circle < Shape
  @var = "circlehoo"

  def display_class_instance_var
    puts Circle.var
  end
end

Shape.new.display_class_instance_var
Rectangle.new.display_class_instance_var
Circle.new.display_class_instance_var
Rectangle.new.display_class_instance_var
Shape.new.display_class_instance_var

--output:--
shapehoo
recthoo
circlehoo
recthoo
shapehoo

与普通实例变量一样,类实例变量是私有的,因此如果想要访问它们,您需要提供访问器方法。这些访问器方法需要在类的单例类中定义,您可以使用以下语法打开单例类:
class <<self

end

新增:

关于这段代码:

class Rectangle < Shape

    @length
    @width

    def initialize ( l,w )
        @length = l
        @width = w
    end

在你的initialize()方法中,你没有设置在方法上面声明的@length和@width变量。在Ruby中,@变量会附加到创建@变量时的self对象。以下是更详细的代码:
class Rectangle < Shape
    #self=Rectangle class
    @length
    @width

    def initialize ( l,w )
        #self=a new instance of the Rectangle class created by initialize
        @length = l
        @width = w
    end

因此,在initialize()中创建的@variables会附加到新实例上,而在initialize()上面声明的@variables会附加到Rectangle类上,这意味着它们是完全不同的变量。

为什么要使用"class << self"而不是只使用accessor?为什么要调用"Rectangle.var"而不是"self.var"或者"@var"?这只是一个问题 ;) - Lukas Baliak
@Lukas Baliak,1)“为什么使用class <<self而不是只使用访问器?”——因为在类级别调用attr_accessor将为名为@var的实例变量创建访问器,而不是为名为@var的类实例变量创建访问器。2)“为什么要调用Rectangle.var而不是self.var?”——因为在实例方法中,self等于调用该方法的实例,但是访问器方法是在类对象上定义的,所以您需要使用类对象调用访问器。您可以编写self.class.var - 7stud
@LukasBaliak,不用谢。我猜操作员根本不想使用类变量。 - 7stud

4
你可以使用"super"来调用父类初始化块并定义实例变量"@var"。 在这种情况下,你可以修改另一个实例的此实例变量的值。就像这样:
class Shape
  def initialize ()
    @var = "woohoo"
  end
end

class Rectangle < Shape
  def initialize(l, w)
    @length = l
    @width = w
    super()
  end

  def area()
    print @var
    return @length * @width
  end

  def var=(new_value)
    @var = new_value
  end
end

a = Rectangle.new(1,1)
a.area
# => woohoo1
a.var = "kaboom"
a.area
# => kaboom1

b = Rectangle.new(2,2)
b.area
# => woohoo4

当然,您也可以使用attr_accessor。

class Shape
  def initialize
    @var = "woohoo"
  end
end

class Rectangle < Shape

  attr_accessor :var
  def initialize(l, w)
    @length, @width = l, w
    super()
  end

  def area()
    print @var
    return @length * @width
  end
end

a = Rectangle.new(1,1)
a.area
# => woohoo1
a.var = "kaboom"
a.area
# => kaboom1

b = Rectangle.new(2,2)
b.area
# => woohoo4

并定义类变量“@var”。 你的代码没有定义任何类型的类变量。 实例变量的重要特点是它们可以为每个实例设置不同的值,而类(实例)变量对于所有实例都具有相同的值。 - 7stud
如果Shape的初始化器有一些参数在Rectangle的初始化器中不存在,该怎么办? - sparkle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接