interface 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +12 -0
- data/MANIFEST +6 -9
- data/examples/example_instance.rb +30 -0
- data/examples/example_interface.rb +27 -0
- data/examples/example_sub.rb +34 -0
- data/examples/example_unrequire.rb +26 -0
- data/lib/interface.rb +54 -25
- data/test/test_interface.rb +66 -0
- metadata +65 -35
- data/test/tc_interface.rb +0 -53
data/CHANGES
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
== 1.0.1 - 29-Jul-2009
|
2
|
+
* Now compatible with Ruby 1.9.x.
|
3
|
+
* Replaced the install.rb with a Rakefile and various tasks.
|
4
|
+
* Updated the license to Artistic 2.0.
|
5
|
+
* Added test-unit 2.x as a development dependency and refactored the test
|
6
|
+
suite to take advantage of some of its features.
|
7
|
+
* Renamed the test file to test_interface.rb.
|
8
|
+
* Renamed the example programs to all start with 'example_' to avoid any
|
9
|
+
possible confusion with actual test suites.
|
10
|
+
* Added rake tasks for running the example programs.
|
11
|
+
* Updated and refactored the gemspec.
|
12
|
+
|
1
13
|
== 1.0.0 - 5-Jun-2005
|
2
14
|
* Re-released on RubyForge.
|
3
15
|
* Some test suite and doc changes.
|
data/MANIFEST
CHANGED
@@ -1,14 +1,11 @@
|
|
1
1
|
CHANGES
|
2
2
|
MANIFEST
|
3
3
|
README
|
4
|
-
|
4
|
+
Rakefile
|
5
5
|
interface.gemspec
|
6
|
-
|
7
|
-
examples/
|
8
|
-
examples/
|
9
|
-
examples/
|
10
|
-
examples/test_unrequire.rb
|
11
|
-
|
6
|
+
examples/example_instance.rb
|
7
|
+
examples/example_interface.rb
|
8
|
+
examples/example_sub.rb
|
9
|
+
examples/example_unrequire.rb
|
12
10
|
lib/interface.rb
|
13
|
-
|
14
|
-
test/tc_interface.rb
|
11
|
+
test/test_interface.rb
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#######################################################################
|
2
|
+
# example_instance.rb
|
3
|
+
#
|
4
|
+
# Sample program to demonstrate extending an interface to an instance
|
5
|
+
# of a class. You can run this program via the 'rake example_instance'
|
6
|
+
# task. Modify as you see fit.
|
7
|
+
#######################################################################
|
8
|
+
require 'interface'
|
9
|
+
|
10
|
+
MyInterface = interface{
|
11
|
+
required_methods :foo, :bar
|
12
|
+
}
|
13
|
+
|
14
|
+
class Foo
|
15
|
+
def foo; end
|
16
|
+
def bar; end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Bar
|
20
|
+
end
|
21
|
+
|
22
|
+
f = Foo.new
|
23
|
+
f.extend(MyInterface)
|
24
|
+
|
25
|
+
b = Bar.new
|
26
|
+
|
27
|
+
# This will blow up
|
28
|
+
class << b
|
29
|
+
include MyInterface
|
30
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#######################################################################
|
2
|
+
# example_interface.rb
|
3
|
+
#
|
4
|
+
# Sample test script that demonstrates a typical interface. You can
|
5
|
+
# run this example via the 'rake example_interface' task. Modify this
|
6
|
+
# code as you see fit.
|
7
|
+
#######################################################################
|
8
|
+
require 'interface'
|
9
|
+
|
10
|
+
MyInterface = interface{
|
11
|
+
required_methods :foo, :bar
|
12
|
+
}
|
13
|
+
|
14
|
+
class MyClass
|
15
|
+
def foo; end
|
16
|
+
def bar; end
|
17
|
+
include MyInterface
|
18
|
+
end
|
19
|
+
|
20
|
+
=begin
|
21
|
+
# Raises an error until bar is defined
|
22
|
+
class Foo
|
23
|
+
def foo
|
24
|
+
puts "foo"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
=end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#######################################################################
|
2
|
+
# example_sub.rb
|
3
|
+
#
|
4
|
+
# Sample program to demonstrate extending a sub-interface. You can
|
5
|
+
# run this program via the 'rake example_sub' task. Modify this code
|
6
|
+
# as you see fit.
|
7
|
+
#######################################################################
|
8
|
+
require 'interface'
|
9
|
+
|
10
|
+
module MyInterface
|
11
|
+
extend Interface
|
12
|
+
required_methods :foo, :bar
|
13
|
+
end
|
14
|
+
|
15
|
+
module MySubInterface
|
16
|
+
extend Interface
|
17
|
+
extend MyInterface
|
18
|
+
required_methods :baz
|
19
|
+
end
|
20
|
+
|
21
|
+
class MyClass
|
22
|
+
def baz; end
|
23
|
+
def bar; end
|
24
|
+
def foo; end
|
25
|
+
include MySubInterface
|
26
|
+
end
|
27
|
+
|
28
|
+
=begin
|
29
|
+
# Raises an error
|
30
|
+
class MyClass
|
31
|
+
def baz; end
|
32
|
+
include MyInterface
|
33
|
+
end
|
34
|
+
=end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
###########################################################################
|
2
|
+
# example_unrequire.rb
|
3
|
+
#
|
4
|
+
# Sample test script for to verify that unrequired_methods works properly.
|
5
|
+
# You can run this code via the 'rake example_unrequire' rake task. Modify
|
6
|
+
# this code as you see fit.
|
7
|
+
###########################################################################
|
8
|
+
require 'interface'
|
9
|
+
|
10
|
+
MyInterface = interface{
|
11
|
+
required_methods :foo, :bar
|
12
|
+
}
|
13
|
+
|
14
|
+
# require foo and baz, but not bar
|
15
|
+
MySubInterface = interface{
|
16
|
+
extends MyInterface
|
17
|
+
required_methods :baz
|
18
|
+
unrequired_methods :bar
|
19
|
+
}
|
20
|
+
|
21
|
+
# No error
|
22
|
+
class MyClass
|
23
|
+
def foo; end
|
24
|
+
def baz; end
|
25
|
+
include MySubInterface
|
26
|
+
end
|
data/lib/interface.rb
CHANGED
@@ -1,64 +1,93 @@
|
|
1
|
+
# A module for implementing Java style interfaces in Ruby. For more information
|
2
|
+
# about Java interfaces, please see:
|
3
|
+
#
|
4
|
+
# http://java.sun.com/docs/books/tutorial/java/concepts/interface.html
|
5
|
+
#
|
1
6
|
module Interface
|
2
|
-
|
7
|
+
# The version of this library.
|
8
|
+
Interface::VERSION = '1.0.1'
|
3
9
|
|
4
10
|
# Raised if a class or instance does not meet the interface requirements.
|
5
11
|
class MethodMissing < RuntimeError; end
|
12
|
+
|
13
|
+
alias :extends :extend
|
14
|
+
|
15
|
+
private
|
6
16
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
def extend_object(o)
|
13
|
-
return append_features(o) if Interface === o
|
14
|
-
append_features(class << o; self end)
|
15
|
-
included(o)
|
17
|
+
def extend_object(obj)
|
18
|
+
return append_features(obj) if Interface === obj
|
19
|
+
append_features(class << obj; self end)
|
20
|
+
included(obj)
|
16
21
|
end
|
17
22
|
|
18
23
|
def append_features(mod)
|
19
24
|
return super if Interface === mod
|
20
|
-
|
21
|
-
|
25
|
+
|
26
|
+
inherited = (self.ancestors-[self]).select{ |x| Interface === x }
|
27
|
+
inherited = inherited.map{ |x| x.instance_variable_get('@ids') }
|
28
|
+
|
22
29
|
ids = @ids + inherited.flatten
|
23
30
|
@unreq ||= []
|
24
|
-
|
25
|
-
|
26
|
-
|
31
|
+
|
32
|
+
(ids - @unreq).uniq.each do |id|
|
33
|
+
id = id.to_s if RUBY_VERSION.to_f < 1.9
|
34
|
+
unless mod.instance_methods(true).include?(id)
|
35
|
+
raise Interface::MethodMissing, id
|
27
36
|
end
|
28
37
|
end
|
38
|
+
|
29
39
|
super mod
|
30
40
|
end
|
41
|
+
|
42
|
+
public
|
31
43
|
|
32
44
|
# Accepts an array of method names that define the interface. When this
|
33
45
|
# module is included/implemented, those method names must have already been
|
34
46
|
# defined.
|
47
|
+
#
|
35
48
|
def required_methods(*ids)
|
36
49
|
@ids = ids
|
37
50
|
end
|
38
51
|
|
39
52
|
# Accepts an array of method names that are removed as a requirement for
|
40
|
-
# implementation.
|
53
|
+
# implementation. Presumably you would use this in a sub-interface where
|
41
54
|
# you only wanted a partial implementation of an existing interface.
|
55
|
+
#
|
42
56
|
def unrequired_methods(*ids)
|
43
57
|
@unreq ||= []
|
44
58
|
@unreq += ids
|
45
59
|
end
|
46
60
|
end
|
47
61
|
|
48
|
-
#
|
49
|
-
#
|
62
|
+
# The interface method creates an interface module which typically sets
|
63
|
+
# a list of methods that must be defined in the including class or module.
|
64
|
+
# If the methods are not defined, an Interface::MethodMissing error is raised.
|
50
65
|
#
|
51
|
-
#
|
66
|
+
# A interface can extend an existing interface as well. These are called
|
67
|
+
# sub-interfaces, and they can included the rules for their parent interface
|
68
|
+
# by simply extending it.
|
69
|
+
#
|
70
|
+
# Example:
|
71
|
+
#
|
72
|
+
# # Require 'alpha' and 'beta' methods
|
73
|
+
# AlphaInterface = interface{
|
74
|
+
# required_methods :alpha, :beta
|
75
|
+
# }
|
76
|
+
#
|
77
|
+
# # A sub-interface that requires 'beta' and 'gamma' only
|
78
|
+
# GammaInterface = interface{
|
79
|
+
# extends AlphaInterface
|
80
|
+
# required_methods :gamma
|
81
|
+
# unrequired_methods :alpha
|
82
|
+
# }
|
83
|
+
#
|
52
84
|
def interface(&block)
|
53
85
|
mod = Module.new
|
54
|
-
mod.extend
|
86
|
+
mod.extend(Interface)
|
55
87
|
mod.instance_eval(&block)
|
56
88
|
mod
|
57
89
|
end
|
58
90
|
|
59
91
|
class Module
|
60
|
-
|
61
|
-
|
62
|
-
include m
|
63
|
-
end
|
64
|
-
end
|
92
|
+
alias :implements :include
|
93
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
#####################################################
|
2
|
+
# test_interface.rb
|
3
|
+
#
|
4
|
+
# Test suite for the Interface module.
|
5
|
+
#####################################################
|
6
|
+
require 'rubygems'
|
7
|
+
gem 'test-unit'
|
8
|
+
|
9
|
+
require 'test/unit'
|
10
|
+
require 'interface'
|
11
|
+
|
12
|
+
class TC_Interface < Test::Unit::TestCase
|
13
|
+
def self.startup
|
14
|
+
alpha_interface = interface{
|
15
|
+
required_methods :alpha, :beta
|
16
|
+
}
|
17
|
+
|
18
|
+
gamma_interface = interface{
|
19
|
+
extends alpha_interface
|
20
|
+
required_methods :gamma
|
21
|
+
unrequired_methods :alpha
|
22
|
+
}
|
23
|
+
|
24
|
+
# Workaround for 1.9.x
|
25
|
+
@@alpha_interface = alpha_interface
|
26
|
+
@@gamma_interface = gamma_interface
|
27
|
+
|
28
|
+
eval("class A; end")
|
29
|
+
|
30
|
+
eval("
|
31
|
+
class B
|
32
|
+
def alpha; end
|
33
|
+
def beta; end
|
34
|
+
end
|
35
|
+
")
|
36
|
+
|
37
|
+
eval("
|
38
|
+
class C
|
39
|
+
def beta; end
|
40
|
+
def gamma; end
|
41
|
+
end
|
42
|
+
")
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_version
|
46
|
+
assert_equal('1.0.1', Interface::VERSION)
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_interface_requirements_not_met
|
50
|
+
assert_raise(Interface::MethodMissing){ A.extend(@@alpha_interface) }
|
51
|
+
assert_raise(Interface::MethodMissing){ A.new.extend(@@alpha_interface) }
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_sub_interface_requirements_not_met
|
55
|
+
assert_raise(Interface::MethodMissing){ B.extend(@@gamma_interface) }
|
56
|
+
assert_raise(Interface::MethodMissing){ B.new.extend(@@gamma_interface) }
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_alpha_interface_requirements_met
|
60
|
+
assert_nothing_raised{ B.new.extend(@@alpha_interface) }
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_gamma_interface_requirements_met
|
64
|
+
assert_nothing_raised{ C.new.extend(@@gamma_interface) }
|
65
|
+
end
|
66
|
+
end
|
metadata
CHANGED
@@ -1,44 +1,74 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.8.10
|
3
|
-
specification_version: 1
|
4
2
|
name: interface
|
5
3
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.0.
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
- lib
|
11
|
-
email: djberg96@gmail.com
|
12
|
-
homepage: http://www.rubyforge.org/projects/shards
|
13
|
-
rubyforge_project:
|
14
|
-
description:
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Daniel J. Berger
|
15
8
|
autorequire:
|
16
|
-
default_executable:
|
17
9
|
bindir: bin
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-07-29 00:00:00 -06:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: test-unit
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
23
22
|
- !ruby/object:Gem::Version
|
24
|
-
version:
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
- Daniel J. Berger
|
29
|
-
files:
|
30
|
-
- lib/interface.rb
|
31
|
-
- README
|
32
|
-
- CHANGES
|
33
|
-
- MANIFEST
|
34
|
-
- test/tc_interface.rb
|
35
|
-
test_files:
|
36
|
-
- test/tc_interface.rb
|
37
|
-
rdoc_options: []
|
38
|
-
extra_rdoc_files:
|
39
|
-
- README
|
40
|
-
- CHANGES
|
23
|
+
version: 2.0.3
|
24
|
+
version:
|
25
|
+
description: " The interface library implements Java style interfaces for Ruby.\n It lets you define a set a methods that must be defined in the\n including class or module, or an error is raised.\n"
|
26
|
+
email: djberg96@gmail.com
|
41
27
|
executables: []
|
28
|
+
|
42
29
|
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README
|
33
|
+
- CHANGES
|
34
|
+
- MANIFEST
|
35
|
+
files:
|
36
|
+
- examples/example_instance.rb
|
37
|
+
- examples/example_interface.rb
|
38
|
+
- examples/example_sub.rb
|
39
|
+
- examples/example_unrequire.rb
|
40
|
+
- lib/interface.rb
|
41
|
+
- test/test_interface.rb
|
42
|
+
- README
|
43
|
+
- CHANGES
|
44
|
+
- MANIFEST
|
45
|
+
has_rdoc: true
|
46
|
+
homepage: http://www.rubyforge.org/projects/shards
|
47
|
+
licenses:
|
48
|
+
- Artistic 2.0
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
version:
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: "0"
|
65
|
+
version:
|
43
66
|
requirements: []
|
44
|
-
|
67
|
+
|
68
|
+
rubyforge_project: shards
|
69
|
+
rubygems_version: 1.3.5
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: Java style interfaces for Ruby
|
73
|
+
test_files:
|
74
|
+
- test/test_interface.rb
|
data/test/tc_interface.rb
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
#####################################################
|
2
|
-
# tc_interface.rb
|
3
|
-
#
|
4
|
-
# Test suite for the Interface module.
|
5
|
-
#####################################################
|
6
|
-
base = File.basename(Dir.pwd)
|
7
|
-
if base == "test" || base =~ /interface/
|
8
|
-
Dir.chdir("..") if base == "test"
|
9
|
-
$LOAD_PATH.unshift("lib")
|
10
|
-
end
|
11
|
-
|
12
|
-
require "test/unit"
|
13
|
-
require "interface"
|
14
|
-
|
15
|
-
TestInterface = interface{
|
16
|
-
required_methods :foo, :bar
|
17
|
-
}
|
18
|
-
|
19
|
-
TestSubInterface = interface{
|
20
|
-
extend TestInterface
|
21
|
-
required_methods :baz
|
22
|
-
}
|
23
|
-
|
24
|
-
class A; end
|
25
|
-
|
26
|
-
class B
|
27
|
-
def foo; end
|
28
|
-
def bar; end
|
29
|
-
end
|
30
|
-
|
31
|
-
class C < B
|
32
|
-
def baz; end
|
33
|
-
end
|
34
|
-
|
35
|
-
class TC_Interface < Test::Unit::TestCase
|
36
|
-
def test_version
|
37
|
-
assert_equal("1.0.0", Interface::VERSION)
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_requirements_not_met
|
41
|
-
assert_raises(Interface::MethodMissing){
|
42
|
-
A.new.extend(TestInterface)
|
43
|
-
}
|
44
|
-
assert_raises(Interface::MethodMissing){
|
45
|
-
B.new.extend(TestSubInterface)
|
46
|
-
}
|
47
|
-
end
|
48
|
-
|
49
|
-
def test_requirements_met
|
50
|
-
assert_nothing_raised{ B.new.extend(TestInterface) }
|
51
|
-
assert_nothing_raised{ C.new.extend(TestSubInterface) }
|
52
|
-
end
|
53
|
-
end
|