Finalist
Finalist adds final
method modifier.
final
forbids method override.
This gem is pseudo static code analyzer by method_added
and singleton_method_added
and included
and extended
.
it detect final violation when class(module) is defined, not runtime.
Simple case is following.
class A1
extend Finalist
final def foo
end
end
class A2 < A1
def foo # => raise
end
end
This case raises Finalist::OverrideFinalMethodError
at def foo in A2 class
.
This gem supports other cases. (see finalist_spec.rb)
My similar gems
Installation
Add this line to your application's Gemfile:
gem 'finalist'
And then execute:
$ bundle
Or install it yourself as:
$ gem install finalist
Usage
A class or module extends Finalist
module
And add final
modifier to target method.
(final
can accept symbol as method name.)
for Production
If you want to disable Finalist, write Finalist.disable = true
at first line.
If Finalist is disabled, TracePoint never runs, and so there is no overhead of VM instruction.
Examples
include module
module E1
extend Finalist
final def foo
end
end
module E2
include E1
end
module E3
include E2
def foo # => raise
end
end
include module after override
module F1
extend Finalist
final def foo
end
end
class F2
def foo
end
include F1 # => raise
end
class method
class J1
extend Finalist
class << self
final def foo
end
end
end
class J2 < J1
class << self
def foo # => raise
end
end
end
extend object
module H1
extend Finalist
final def foo
end
end
a = "str"
a.extend(H1)
def a.foo # => raise
end
extend object after override
module I1
extend Finalist
final def foo
end
end
a = "str"
def a.foo
end
a.extend(I1) # => raise
class method by extend module
module K1
extend Finalist
final def foo
end
end
class K2
extend K1
class << self
def foo # => raise
end
end
end
class method by extend module after override
module L1
extend Finalist
final def foo
end
end
class L2
class << self
def foo
end
end
extend L1 # => raise
end
overrided by module prepend
This case is a intended loophole.
module M1
extend Finalist
final def foo
end
end
module M3
def foo
"foo"
end
end
class M2
include M1
prepend M3
end
M2.new.foo # => "foo"
How is this implemented?
Use so many ruby hooks. method_added
and singleton_method_added
and included
and extended
.
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/joker1007/finalist.
License
The gem is available as open source under the terms of the MIT License.