嵌套类如何在Ruby中访问外部类中的方法?

时间:2022-11-25 08:23:40
def class A
  def a
    raise "hi" #can't be reached
  end

  class B
    def b
      a() #doesn't find method a.
    end
  end
end

I want to invoke a from b and raise the exception. How can I?

我想从b调用a并引发异常。我怎么能够?

6 个解决方案

#1


25  

Ruby doesn't have nested classes.

Ruby没有嵌套类。

The only way to inherit behavior is, well, via inheritance.

继承行为的唯一方法是通过继承。

If you want your code to work, you need to use a language which supports nested classes. While this is an incredibly neat and powerful feature, I unfortunately know of only two languages that have nested classes:

如果希望代码有效,则需要使用支持嵌套类的语言。虽然这是一个令人难以置信的整洁和强大的功能,但遗憾的是我只知道两种具有嵌套类的语言:

  • BETA, the language which introduced nested classes (and its successor gbeta)
  • BETA,引入嵌套类的语言(及其后继者gbeta)
  • Newspeak
  • 新语

I don't know of any other.

我不知道任何其他的。

Java has a construct called nested classes, but they have some unfortunate design limitations.

Java有一个名为嵌套类的构造,但它们有一些不幸的设计限制。

In your example above, it's not the class B that is nested inside A, it is the constant B that is nested inside A. Think about this:

在上面的例子中,它不是嵌套在A中的B类,它是嵌套在A中的常量B.想想这个:

C = A::B

Now, the class is available under two names: A::B and C. It should be immediately obvious that C is global and not nested inside A. (Well, actually, C is nested inside Object, because there aren't really global constants either, but that's beside the point.) But since C and A::B are the same class, it obviously cannot be both nested and not nested. The only logical conclusion is that the class itself isn't nested.

现在,该类有两个名称:A :: B和C.应该很明显C是全局的而不是嵌套在A中。(实际上,C嵌套在Object中,因为实际上并不是全局的常数,但这不是重点。)但由于C和A :: B是同一个类,它显然不能嵌套而不是嵌套。唯一合乎逻辑的结论是类本身不是嵌套的。

The defining feature of nested classes is that method lookup goes along two dimensions: up the inheritance chain, and outwards through the nesting. Ruby, like 99.9% of all OO languages, only supports the former. (In some sense, nested classes inherit not only the features of their superclass, but also the features of their surrounding class.)

嵌套类的定义特征是方法查找沿着两个维度:向上继承链,向外通过嵌套。 Ruby,就像所有OO语言的99.9%一样,只支持前者。 (在某种意义上,嵌套类不仅继承了它们超类的特性,还继承了它们周围类的特性。)

#2


10  

This is just for the lulz:

这只是为了lulz:

class A
  def a
    puts "hello from a"
  end

  class B
    def b
      Module.nesting[1].new.a()
    end
  end
end

#3


4  

I typically do something like this:

我通常做这样的事情:

class A
  def a
    puts "hi"
  end

  def createB
    B.new self
  end

  class B
    def initialize(parent)
      @parent=parent
    end

    def b
      @parent.a
    end
  end
end

A.new.createB.b

#4


3  

If you want then nested class to extend the outer class, then do so:

如果您希望嵌套类扩展外部类,则执行以下操作:

class Outer

  class Inner < Outer
    def use_outer_method
      outer_method("hi mom!")
    end
  end

  def outer_method(foo)
    puts foo
  end

end

foo = Outer::Inner.new
foo.use_outer_method        #<= "hi mom"
foo.outer_method("hi dad!") #<= "hi dad"

#5


1  

Well depending on your circumstances there is actually a solution, a pretty easy one at that. Ruby allows the catching of method calls that aren't captured by the object. So for your example you could do:

根据您的具体情况,实际上有一个解决方案,一个非常简单的解决方案。 Ruby允许捕获对象未捕获的方法调用。所以对于你的例子,你可以这样做:

def class A
  def a
    raise "hi" #can't be reached
  end

  class B
    def initialize()
      @parent = A.new
    end

    def b
      a() #does find method a.
    end

    def method_missing(*args)
      if @parent.respond_to?(method)
        @parent.send(*args)
      else
        super
      end
    end
  end
end

So then if you do this:

那么如果你这样做:

A::B.new().b

you get:

你得到:

!! #<RuntimeError: hi>

It is probably an easier way to make something like a SubController that only handles certain activities, but can easily call basic controller methods (You would want to send in the parent controller as an argument in the initializer though).

它可能是一种更简单的方法来制作像SubController这样的东西,它只处理某些活动,但可以很容易地调用基本的控制器方法(你可能希望在初始化器中将父控制器作为参数发送)。

Obviously this should be used sparingly, and it can really get confusing if you use it all over the place, but it can be really great to simplify your code.

显然这应该谨慎使用,如果你在整个地方使用它真的会让人感到困惑,但是简化你的代码真的很棒。

#6


0  

Was a supposed to be a class method for class A?

应该是A类的类方法吗?

class A
  def self.a
    raise "hi"
  end
  class B
    def b
      A::a 
    end
  end
end

A::B.new.b

If you want to keep it as an instance method, you'll obviously have call to it on an instance, like for example A.new.a.

如果你想把它作为一个实例方法,你显然会在一个实例上调用它,例如A.new.a.

#1


25  

Ruby doesn't have nested classes.

Ruby没有嵌套类。

The only way to inherit behavior is, well, via inheritance.

继承行为的唯一方法是通过继承。

If you want your code to work, you need to use a language which supports nested classes. While this is an incredibly neat and powerful feature, I unfortunately know of only two languages that have nested classes:

如果希望代码有效,则需要使用支持嵌套类的语言。虽然这是一个令人难以置信的整洁和强大的功能,但遗憾的是我只知道两种具有嵌套类的语言:

  • BETA, the language which introduced nested classes (and its successor gbeta)
  • BETA,引入嵌套类的语言(及其后继者gbeta)
  • Newspeak
  • 新语

I don't know of any other.

我不知道任何其他的。

Java has a construct called nested classes, but they have some unfortunate design limitations.

Java有一个名为嵌套类的构造,但它们有一些不幸的设计限制。

In your example above, it's not the class B that is nested inside A, it is the constant B that is nested inside A. Think about this:

在上面的例子中,它不是嵌套在A中的B类,它是嵌套在A中的常量B.想想这个:

C = A::B

Now, the class is available under two names: A::B and C. It should be immediately obvious that C is global and not nested inside A. (Well, actually, C is nested inside Object, because there aren't really global constants either, but that's beside the point.) But since C and A::B are the same class, it obviously cannot be both nested and not nested. The only logical conclusion is that the class itself isn't nested.

现在,该类有两个名称:A :: B和C.应该很明显C是全局的而不是嵌套在A中。(实际上,C嵌套在Object中,因为实际上并不是全局的常数,但这不是重点。)但由于C和A :: B是同一个类,它显然不能嵌套而不是嵌套。唯一合乎逻辑的结论是类本身不是嵌套的。

The defining feature of nested classes is that method lookup goes along two dimensions: up the inheritance chain, and outwards through the nesting. Ruby, like 99.9% of all OO languages, only supports the former. (In some sense, nested classes inherit not only the features of their superclass, but also the features of their surrounding class.)

嵌套类的定义特征是方法查找沿着两个维度:向上继承链,向外通过嵌套。 Ruby,就像所有OO语言的99.9%一样,只支持前者。 (在某种意义上,嵌套类不仅继承了它们超类的特性,还继承了它们周围类的特性。)

#2


10  

This is just for the lulz:

这只是为了lulz:

class A
  def a
    puts "hello from a"
  end

  class B
    def b
      Module.nesting[1].new.a()
    end
  end
end

#3


4  

I typically do something like this:

我通常做这样的事情:

class A
  def a
    puts "hi"
  end

  def createB
    B.new self
  end

  class B
    def initialize(parent)
      @parent=parent
    end

    def b
      @parent.a
    end
  end
end

A.new.createB.b

#4


3  

If you want then nested class to extend the outer class, then do so:

如果您希望嵌套类扩展外部类,则执行以下操作:

class Outer

  class Inner < Outer
    def use_outer_method
      outer_method("hi mom!")
    end
  end

  def outer_method(foo)
    puts foo
  end

end

foo = Outer::Inner.new
foo.use_outer_method        #<= "hi mom"
foo.outer_method("hi dad!") #<= "hi dad"

#5


1  

Well depending on your circumstances there is actually a solution, a pretty easy one at that. Ruby allows the catching of method calls that aren't captured by the object. So for your example you could do:

根据您的具体情况,实际上有一个解决方案,一个非常简单的解决方案。 Ruby允许捕获对象未捕获的方法调用。所以对于你的例子,你可以这样做:

def class A
  def a
    raise "hi" #can't be reached
  end

  class B
    def initialize()
      @parent = A.new
    end

    def b
      a() #does find method a.
    end

    def method_missing(*args)
      if @parent.respond_to?(method)
        @parent.send(*args)
      else
        super
      end
    end
  end
end

So then if you do this:

那么如果你这样做:

A::B.new().b

you get:

你得到:

!! #<RuntimeError: hi>

It is probably an easier way to make something like a SubController that only handles certain activities, but can easily call basic controller methods (You would want to send in the parent controller as an argument in the initializer though).

它可能是一种更简单的方法来制作像SubController这样的东西,它只处理某些活动,但可以很容易地调用基本的控制器方法(你可能希望在初始化器中将父控制器作为参数发送)。

Obviously this should be used sparingly, and it can really get confusing if you use it all over the place, but it can be really great to simplify your code.

显然这应该谨慎使用,如果你在整个地方使用它真的会让人感到困惑,但是简化你的代码真的很棒。

#6


0  

Was a supposed to be a class method for class A?

应该是A类的类方法吗?

class A
  def self.a
    raise "hi"
  end
  class B
    def b
      A::a 
    end
  end
end

A::B.new.b

If you want to keep it as an instance method, you'll obviously have call to it on an instance, like for example A.new.a.

如果你想把它作为一个实例方法,你显然会在一个实例上调用它,例如A.new.a.