将 Ruby 方法与子类中的重写隔离开来? (如Java的私有方法)

发布于 2024-08-05 09:49:33 字数 1137 浏览 1 评论 0原文

在 Ruby 中,我想实现像这样的 Java 示例:

class A {        
    private void f() {  System.out.println("Hello world"); }
    public  void g() { f(); }
}
class B extends A {
    public void f() { throw new RuntimeException("bad guy");}
}
public class Try {
    public static void main(String[] args) { new B().g();}
}

这将在 Java 中打印“Hello world”,但是直接的 Ruby 记录:

class A   
    def g; f; end 
    private
    def f; puts "Hello world"; end
end
class B < A
    def f; raise "bad guy"; end
end
B.new.g    # want greet

当然会引发一个坏人 - 由于方法查找机制的差异(我意识到这些语言之间“私有”的含义非常不同)

有什么方法可以达到类似的效果吗? 我并不真正关心可见性,实际上更喜欢这里的所有公共方法。 我的目标只是将超类中的方法与子类中的重写隔离开来(这会破坏其他基方法)。

我想如果有一个解决方案,也可以与模块/包含一起使用?

module BaseAPI 
   def f; puts "Hello world"; end
   def g; f; end;
end
module ExtAPI 
  include BaseAPI
  # some magic here to isolate base method :f from the following one?
  def f; raise "bad guy"; end # could actually be something useful, but interfering with base 'g'
end
include ExtAPI
g # want greet

后续:这看起来是一种罕见的情况,Java 可以实现某些功能,而 Ruby 则不行:-/

In Ruby, I'd like to acheive something like this Java sample:

class A {        
    private void f() {  System.out.println("Hello world"); }
    public  void g() { f(); }
}
class B extends A {
    public void f() { throw new RuntimeException("bad guy");}
}
public class Try {
    public static void main(String[] args) { new B().g();}
}

This will print "Hello world" in Java, but the straight Ruby transcript:

class A   
    def g; f; end 
    private
    def f; puts "Hello world"; end
end
class B < A
    def f; raise "bad guy"; end
end
B.new.g    # want greet

will of course raise a bad guy - due to differences in method lookup mechanism (I realise the meaning of 'private' is very different between these languages)

Is there any way to achieve a similar effect?
I don't really care about visibility, would actually prefer all public methods here.
My goal is simply to isolate a method in the superclass from overriding in subclasses (which would break the other base methods).

I guess if there is a solution, that would work with modules/includes, too?

module BaseAPI 
   def f; puts "Hello world"; end
   def g; f; end;
end
module ExtAPI 
  include BaseAPI
  # some magic here to isolate base method :f from the following one?
  def f; raise "bad guy"; end # could actually be something useful, but interfering with base 'g'
end
include ExtAPI
g # want greet

Follow-up: this looks to be the rare case where something is possible with Java but not with Ruby :-/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无远思近则忧 2024-08-12 09:49:33
class A
  def g
    real_f
  end 
  private
  def f
    real_f
  end
  def real_f
    puts "Hello world"
  end
end
class B < A
  def f
    raise "bad guy"
  end
end
B.new.g    # want hello world

我有一种感觉,这些显而易见的答案并不是你想要的。 Ruby 只是没有执行机制。但郑重声明,我们可以构建一个替代的 AA 级。您甚至可以比这更聪明,并使用 method_missing() 动态插入别名方法。

class A
  def g
    f
  end 
  def f
    puts "Hello world"
  end
end
class AA
  def initialize
    @x = A.new
  end
  def g
    @x.g
  end
  def f
    @x.f
  end
end
class B < AA
  def f
    raise "bad guy"
  end
end
B.new.g    # want hello world
class A
  def g
    real_f
  end 
  private
  def f
    real_f
  end
  def real_f
    puts "Hello world"
  end
end
class B < A
  def f
    raise "bad guy"
  end
end
B.new.g    # want hello world

I have a feeling these obvious answers aren't what you want. Ruby just doesn't have enforcement mechanisms. But just for the record, we could construct a replacement class AA. You could even be more clever than this, and use the method_missing() to dynamically insert alias methods.

class A
  def g
    f
  end 
  def f
    puts "Hello world"
  end
end
class AA
  def initialize
    @x = A.new
  end
  def g
    @x.g
  end
  def f
    @x.f
  end
end
class B < AA
  def f
    raise "bad guy"
  end
end
B.new.g    # want hello world
橘味果▽酱 2024-08-12 09:49:33
class A;   def g;f;end ; private ;def f;puts "Hello world";end;end
class B < A 

  def self.method_added(name)
    if superclass.method_defined? name  or superclass.private_method_defined? name
      raise "A trial to add a new instance method: #{name}, this is not allowed." 
    end
  end 

  def f;raise "bad guy";end;

end
#=>`method_added': A trial to add a new instance method: f,
#   this is not allowed.(RuntimeError)
class A;   def g;f;end ; private ;def f;puts "Hello world";end;end
class B < A 

  def self.method_added(name)
    if superclass.method_defined? name  or superclass.private_method_defined? name
      raise "A trial to add a new instance method: #{name}, this is not allowed." 
    end
  end 

  def f;raise "bad guy";end;

end
#=>`method_added': A trial to add a new instance method: f,
#   this is not allowed.(RuntimeError)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文