是否可以在 Ruby 中复制来自 Java 的覆盖注释?
Is it possible to replicate the Override Annotation from Java in Ruby?
我知道在 Java 中,Override 注释检查超类是否有方法:
class Animal {
public void speak () {
System.out.println("Hello!");
}
}
class Dog extends Animal {
@override
public void eat () { //this kind of stuff
System.out.println("omnomnom");
}
}
有没有办法在 Ruby 中执行此操作(作为函数或其他)?
这可行,但有点冗长:
class OverrideError < StandardError
def initialize a
super("the superclass of `#{a[0]}`(`#{a[0].superclass}`) does not contain the method that has been attempeted to Override: `#{a[1]}`")
end
end
#this function help the _override_ function ignore string literals
def delQ str
str = str.gsub(/(".*"|'.*'|\%[qQ]?\{.*\})/, "")
while /\= ?\<\<\-?[\w\_\?\!]+ /.match?(str)
x = /\= ?\<\<\-?[\w\_\?\!]+ /.match(str)[0]
stopname = x.sub(/\= ?\<\<\-?/, "")
locat = str =~ /\= ?\<\<\-?[\w\_\?\!]+ .*/
part = str.slice(locat)
stop = part =~ %r{stopname}
part1 = part.sub(%r{x + ".*" + stopname}, "")
str = str.sub(part, part1)
end
return str
end
def _override_
file = File.read("./" + caller[0][/[^:]+/]).split("\n")
loc = (caller[0].to_s.scan(/\d+/).first).to_i
line = file[loc]
method = /def (self(\.|::))?[\w\_\?\!]+/.match(line)[0]
method = method.gsub(/(def|self|\.|::|\s)/, "")
clname = ""
file = file.join("\n")
file = delQ(file)
file = file.split("\n")
while loc >= 0
substr = file[loc].gsub(/(\t|\n)/, "")
if substr.start_with?("class ")
clname = file[loc].gsub(/\t/, "").sub("class ", "")
clname = /[\w_\?\!]+/.match(clname)[0]
break
end
loc -= 1
end
clname = Kernel.const_get(clname)
hmm = clname.superclass.method_defined?(method.to_sym)
unless hmm
raise OverrideError, [clname, method]
end
end
如何使用它的演示:
class Animal
def initialize name
@name = name
end
def speak
puts "Hello!"
end
end
class Dog < Animal
def initialize name
super name
end
_override_
def speak
# no error
puts "woof!"
end
_override_
def eat
#Traceback (most recent call last):
# 2: from main.rb:11:in `<main>'
# 1: from main.rb:19:in `<class:Dog>'
#/home/runner/Annotations/override.rb:41:in `_override_': the superclass #of `Dog`(`Animal`) does not contain the method that has been attempted #to Override: `eat` (OverrideError)
puts "omnomnom"
end
end
使用在顶级特征class上定义的class方法会相对容易一些。
class Animal
def speak; :ok; end
def self.override *ms
ms = ms - Animal.instance_methods
puts "⚠️ #{ms.inspect} method(s) missing " \
"in #{self}’s ancestors" unless ms.empty?
end
end
class Dog < Animal
override :speak
def speak; :ok; end
override :eat
def eat; :ok; end
end
以上将打印
# ⚠️ [:eat] method(s) missing in Dog’s ancestors
此处对 override
的调用类似于使用参数调用 Module#module_function
,并且可以放置在代码中的任何位置,根据需要接受任意数量的方法名称。
它也可以用 eigenclass 实例变量来完成,使它看起来更像 java 版本。
class Animal
def speak
:ok
end
def self.inherited(base)
base.instance_variable_set(:@override, ->(*ms) {
ms = ms - Animal.instance_methods
puts "⚠️ #{ms.inspect} method(s) without super" \
unless ms.empty?
})
end
end
class Dog < Animal
@override[:speak]
def speak; :ok; end
@override[:eat]
def eat; :ok; end
end
也可以在 TracePoint
and/or Module#method_added
的帮助下 完全 复制 Java 语法,但我发现它不太明确并且会避免支持直接方法名称传递如上所示。
采用 ,您可以通过将其移动到模块中来提高其可重用性。
module Overridable
def override(*methods)
diff = methods - superclass.instance_methods
return if diff.empty?
puts "⚠ #{diff.inspect} method(s) missing from #{superclass}"
end
end
您可以在基础 class Animal
中扩展模块,这样所有继承自 Animal
的子 class 都有 override
方法。或者您可以选择只扩展特定的子class.
class Animal
# make :override available in all subclasses
extend Overridable
end
或者假设上面没有设置。
class Dog < Animal
# make :override available in only this subclass
extend Overridable
end
我知道在 Java 中,Override 注释检查超类是否有方法:
class Animal {
public void speak () {
System.out.println("Hello!");
}
}
class Dog extends Animal {
@override
public void eat () { //this kind of stuff
System.out.println("omnomnom");
}
}
有没有办法在 Ruby 中执行此操作(作为函数或其他)?
这可行,但有点冗长:
class OverrideError < StandardError
def initialize a
super("the superclass of `#{a[0]}`(`#{a[0].superclass}`) does not contain the method that has been attempeted to Override: `#{a[1]}`")
end
end
#this function help the _override_ function ignore string literals
def delQ str
str = str.gsub(/(".*"|'.*'|\%[qQ]?\{.*\})/, "")
while /\= ?\<\<\-?[\w\_\?\!]+ /.match?(str)
x = /\= ?\<\<\-?[\w\_\?\!]+ /.match(str)[0]
stopname = x.sub(/\= ?\<\<\-?/, "")
locat = str =~ /\= ?\<\<\-?[\w\_\?\!]+ .*/
part = str.slice(locat)
stop = part =~ %r{stopname}
part1 = part.sub(%r{x + ".*" + stopname}, "")
str = str.sub(part, part1)
end
return str
end
def _override_
file = File.read("./" + caller[0][/[^:]+/]).split("\n")
loc = (caller[0].to_s.scan(/\d+/).first).to_i
line = file[loc]
method = /def (self(\.|::))?[\w\_\?\!]+/.match(line)[0]
method = method.gsub(/(def|self|\.|::|\s)/, "")
clname = ""
file = file.join("\n")
file = delQ(file)
file = file.split("\n")
while loc >= 0
substr = file[loc].gsub(/(\t|\n)/, "")
if substr.start_with?("class ")
clname = file[loc].gsub(/\t/, "").sub("class ", "")
clname = /[\w_\?\!]+/.match(clname)[0]
break
end
loc -= 1
end
clname = Kernel.const_get(clname)
hmm = clname.superclass.method_defined?(method.to_sym)
unless hmm
raise OverrideError, [clname, method]
end
end
如何使用它的演示:
class Animal
def initialize name
@name = name
end
def speak
puts "Hello!"
end
end
class Dog < Animal
def initialize name
super name
end
_override_
def speak
# no error
puts "woof!"
end
_override_
def eat
#Traceback (most recent call last):
# 2: from main.rb:11:in `<main>'
# 1: from main.rb:19:in `<class:Dog>'
#/home/runner/Annotations/override.rb:41:in `_override_': the superclass #of `Dog`(`Animal`) does not contain the method that has been attempted #to Override: `eat` (OverrideError)
puts "omnomnom"
end
end
使用在顶级特征class上定义的class方法会相对容易一些。
class Animal
def speak; :ok; end
def self.override *ms
ms = ms - Animal.instance_methods
puts "⚠️ #{ms.inspect} method(s) missing " \
"in #{self}’s ancestors" unless ms.empty?
end
end
class Dog < Animal
override :speak
def speak; :ok; end
override :eat
def eat; :ok; end
end
以上将打印
# ⚠️ [:eat] method(s) missing in Dog’s ancestors
此处对 override
的调用类似于使用参数调用 Module#module_function
,并且可以放置在代码中的任何位置,根据需要接受任意数量的方法名称。
它也可以用 eigenclass 实例变量来完成,使它看起来更像 java 版本。
class Animal
def speak
:ok
end
def self.inherited(base)
base.instance_variable_set(:@override, ->(*ms) {
ms = ms - Animal.instance_methods
puts "⚠️ #{ms.inspect} method(s) without super" \
unless ms.empty?
})
end
end
class Dog < Animal
@override[:speak]
def speak; :ok; end
@override[:eat]
def eat; :ok; end
end
也可以在 TracePoint
and/or Module#method_added
的帮助下 完全 复制 Java 语法,但我发现它不太明确并且会避免支持直接方法名称传递如上所示。
采用
module Overridable
def override(*methods)
diff = methods - superclass.instance_methods
return if diff.empty?
puts "⚠ #{diff.inspect} method(s) missing from #{superclass}"
end
end
您可以在基础 class Animal
中扩展模块,这样所有继承自 Animal
的子 class 都有 override
方法。或者您可以选择只扩展特定的子class.
class Animal
# make :override available in all subclasses
extend Overridable
end
或者假设上面没有设置。
class Dog < Animal
# make :override available in only this subclass
extend Overridable
end