interface 1.0.0

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.
Files changed (6) hide show
  1. data/CHANGES +6 -0
  2. data/MANIFEST +14 -0
  3. data/README +82 -0
  4. data/lib/interface.rb +64 -0
  5. data/test/tc_interface.rb +53 -0
  6. metadata +44 -0
data/CHANGES ADDED
@@ -0,0 +1,6 @@
1
+ == 1.0.0 - 5-Jun-2005
2
+ * Re-released on RubyForge.
3
+ * Some test suite and doc changes.
4
+
5
+ == 0.1.0 - 9-May-2004
6
+ * Initial release
data/MANIFEST ADDED
@@ -0,0 +1,14 @@
1
+ CHANGES
2
+ MANIFEST
3
+ README
4
+ install.rb
5
+ interface.gemspec
6
+
7
+ examples/test_instance.rb
8
+ examples/test_interface.rb
9
+ examples/test_sub.rb
10
+ examples/test_unrequire.rb
11
+
12
+ lib/interface.rb
13
+
14
+ test/tc_interface.rb
data/README ADDED
@@ -0,0 +1,82 @@
1
+ == Description
2
+ This module provides Java style interfaces for Ruby, including a fairly
3
+ similar syntax. I don't necessarily believe in interfaces, but I wanted to
4
+ put it out there as proof that it could be done. Frankly, Java needs mixins
5
+ more than Ruby needs interfaces, but here you go.
6
+
7
+ == Installation
8
+
9
+ === Manual
10
+ ruby test/ts_interface.rb
11
+ ruby install.rb
12
+
13
+ === Gem Install
14
+ ruby interface.gemspec
15
+ gem install interface-<version>.gem
16
+
17
+ == Synopsis
18
+ require "interface"
19
+
20
+ MyInterface = interface{
21
+ required_methods :foo, :bar, :baz
22
+ }
23
+
24
+ # Raises an error until 'baz' is defined
25
+ class MyClass
26
+ def foo
27
+ puts "foo"
28
+ end
29
+ def bar
30
+ puts "bar"
31
+ end
32
+ implements MyInterface
33
+ end
34
+
35
+ == General Notes
36
+ Subinterfaces work as well. See the test_sub.rb file under the 'test'
37
+ directory for a sample.
38
+
39
+ == Developer's Notes
40
+ A discussion on IRC with Mauricio Fernandez got us talking about traits.
41
+ During that discussion I remembered a blog entry by David Naseby. I
42
+ revisited his blog entry (at http://homepages.ihug.com.au/~naseby/33.html)
43
+ and took a closer look.
44
+
45
+ Keep in mind that I also happened to be thinking about Java at the moment
46
+ because of a recent job switch that involved coding in Java. I was also
47
+ trying to figure out what the purpose of interfaces were.
48
+
49
+ As I read the first page of David Naseby's article I realized that,
50
+ whether intended or not, he had implemented a rudimentary form of interfaces
51
+ for Ruby. When I discovered this, I talked about it some more with Mauricio
52
+ and he and I (mostly him) fleshed out the rest of the module, including some
53
+ syntax improvements. The result is syntax and functionality that is nearly
54
+ identical to Java.
55
+
56
+ I should note that, although I am listed as the author, this was mostly the
57
+ combined work of David Naseby and Mauricio Fernandez. I just happened to be
58
+ the guy that put it all together.
59
+
60
+ == Acknowledgements
61
+ This module was largely inspired and somewhat copied from a post by
62
+ David Naseby at http://homepages.ihug.com.au/~naseby/33.html. It was
63
+ subsequently modified almost entirely by Mauricio Fernandez through a
64
+ series of discussions on IRC.
65
+
66
+ == Copyright
67
+ (C) 2004 Daniel J. Berger
68
+ All rights reserved.
69
+
70
+ == Warranty
71
+ This package is provided "as is" and without any express or
72
+ implied warranties, including, without limitation, the implied
73
+ warranties of merchantability and fitness for a particular purpose.
74
+
75
+ == License
76
+ Ruby's
77
+
78
+ == Author
79
+ Daniel J. Berger (who mostly stole it from David Naseby, which was then
80
+ modified by Mauricio Fernandez)
81
+ djberg96 at gmail dot com
82
+ imperator on IRC (irc.freenode.net)
data/lib/interface.rb ADDED
@@ -0,0 +1,64 @@
1
+ module Interface
2
+ Interface::VERSION = "1.0.0"
3
+
4
+ # Raised if a class or instance does not meet the interface requirements.
5
+ class MethodMissing < RuntimeError; end
6
+
7
+ # An alias for +extend+
8
+ def extends(o)
9
+ extend o
10
+ end
11
+
12
+ def extend_object(o)
13
+ return append_features(o) if Interface === o
14
+ append_features(class << o; self end)
15
+ included(o)
16
+ end
17
+
18
+ def append_features(mod)
19
+ return super if Interface === mod
20
+ inherited = (self.ancestors-[self]).select{|x| Interface === x}.
21
+ map{|x| x.instance_variable_get("@ids")}
22
+ ids = @ids + inherited.flatten
23
+ @unreq ||= []
24
+ (ids-@unreq).uniq.each do |id|
25
+ unless mod.instance_methods( true ).include?( id.to_s )
26
+ raise Interface::MethodMissing, id.to_s
27
+ end
28
+ end
29
+ super mod
30
+ end
31
+
32
+ # Accepts an array of method names that define the interface. When this
33
+ # module is included/implemented, those method names must have already been
34
+ # defined.
35
+ def required_methods(*ids)
36
+ @ids = ids
37
+ end
38
+
39
+ # Accepts an array of method names that are removed as a requirement for
40
+ # implementation. Presumably, you would use this in a subinterface where
41
+ # you only wanted a partial implementation of an existing interface.
42
+ def unrequired_methods(*ids)
43
+ @unreq ||= []
44
+ @unreq += ids
45
+ end
46
+ end
47
+
48
+ # Accepts a block. There are only two methods you should ever pass to this
49
+ # block: required_methods and/or unrequired_methods.
50
+ #
51
+ # Subinterfaces will need to 'extend' their parent interface.
52
+ def interface(&block)
53
+ mod = Module.new
54
+ mod.extend Interface
55
+ mod.instance_eval(&block)
56
+ mod
57
+ end
58
+
59
+ class Module
60
+ # An alias for +include+. This should be the last statement in your class.
61
+ def implements m
62
+ include m
63
+ end
64
+ end
@@ -0,0 +1,53 @@
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
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.10
3
+ specification_version: 1
4
+ name: interface
5
+ version: !ruby/object:Gem::Version
6
+ version: 1.0.0
7
+ date: 2005-06-05
8
+ summary: Java style interfaces for ruby
9
+ require_paths:
10
+ - lib
11
+ email: djberg96@gmail.com
12
+ homepage: http://www.rubyforge.org/projects/shards
13
+ rubyforge_project:
14
+ description:
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ -
22
+ - ">"
23
+ - !ruby/object:Gem::Version
24
+ version: 0.0.0
25
+ version:
26
+ platform: ruby
27
+ authors:
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
41
+ executables: []
42
+ extensions: []
43
+ requirements: []
44
+ dependencies: []