Class: SubObject

Inherits:
Object
  • Object
show all
Defined in:
lib/sub_object.rb,
lib/sub_object/sub_array.rb

Overview

Parent class for SubString and SubObject::SubArray or similar.

Summary

This class SubObject is the parent class for SubString and alike. This class expresses Ruby sub-Object (like Sub-String), which are obtained with the self[i, j] method, but taking up negligible memory space, as its instance internally holds the (likely positional, though arbitrary) information (i, j) only. It provides the basic interface so the instance behaves exactly like the original class (String for SubString, for example) as duck-typing, except destructive modification, which is prohibited.

If the original object is destructively modified in a way it changes its hash value, warning is issued whenever this instance is accessed.

Important note to the developers

To inherit this class, make sure to include the lines equivalent to the following 2 lines, replacing the method name :to_str (which is for SubString class) to suit your child class.

TO_SOURCE_METHOD = :to_str
alias_method TO_SOURCE_METHOD, :to_source

The full reference is found in the top page SubObject and in Github

Author:

  • Masa Sakano (Wise Babel Ltd)

Direct Known Subclasses

SubArray

Defined Under Namespace

Classes: SubArray

Constant Summary collapse

TO_SOURCE_METHOD =

Symbol of the method that projects to (returns) the original-like instance; e.g., :to_str for String. The value should be overwritten in the child class of SubObject.

:itself
DESTRUCTIVE_METHODS =

List of the names (String) of destructive methods (other than those ending with “!”).

%w( []= << clear concat force_encoding insert prepend replace )

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source, pos, size, attr: nil) ⇒ SubObject

Returns a new instance of SubObject equivalent to source[ pos, size ]

Parameters:

  • source (Object)

    source Object

  • pos (Integer, Object)

    The first index for the method #[], usually the starting index position.

  • size (Integer, Object)

    The second index for the method #[], usually the size.

  • attr: (Object) (defaults to: nil)

    user-specified arbitrary object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/sub_object.rb', line 93

def initialize(source, pos, size, attr: nil)
  @source, @pos, @isize = source, pos, size
  @attr = attr

  # Sanity check
  begin
    _ = @source[@pos, @isize]
  rescue NoMethodError
    raise TypeError, ERR_MSGS[:no_method_error]
  rescue ArgumentError
    raise TypeError, ERR_MSGS[:argument_error]
  rescue TypeError
    raise TypeError, ERR_MSGS[:type_error]%[pos.inspect, size.inspect]
  end

  if !source.respond_to? self.class::TO_SOURCE_METHOD
    raise TypeError, "Wrong source class #{source.class.name} for this class #{self.class.name}"
  end

  # Hash value retained to check its potential destructive change
  @hash = @source.hash
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *rest, &block) ⇒ Object

method_missing for any but destructive methods

Returns:

  • (Object)

See Also:



192
193
194
# File 'lib/sub_object.rb', line 192

def method_missing(method_name, *rest, &block)
  destructive_method?(method_name) ? super : to_source.send(method_name, *rest, &block)
end

Instance Attribute Details

#attrObject

Setter/Getter of the attribute. nil in default.



85
86
87
# File 'lib/sub_object.rb', line 85

def attr
  @attr
end

#posObject (readonly)

Starting (character) position



82
83
84
# File 'lib/sub_object.rb', line 82

def pos
  @pos
end

Class Method Details

.verboseObject

Getter of the class instance variable @verbosity



61
62
63
# File 'lib/sub_object.rb', line 61

def self.verbose
  (defined? @verbosity) ? @verbosity : nil
end

.verbose=(obj) ⇒ Object

Setter of the class instance variable @@verbosity



66
67
68
# File 'lib/sub_object.rb', line 66

def self.verbose=(obj)
  @verbosity=obj
end

Instance Method Details

#<=>(*rest) ⇒ Object

Redefining a method in Object to evaluate via #to_source



176
# File 'lib/sub_object.rb', line 176

def <=>(      *rest); to_source.send(__method__, *rest); end

#==(*rest) ⇒ Object

Redefining a method in Object to evaluate via #to_source



166
# File 'lib/sub_object.rb', line 166

def ==(       *rest); to_source.send(__method__, *rest); end

#===(*rest) ⇒ Object

Redefining a method in Object to evaluate via #to_source



168
# File 'lib/sub_object.rb', line 168

def ===(      *rest); to_source.send(__method__, *rest); end

#=~(*rest) ⇒ Object

Redefining a method in Object to evaluate via #to_source



174
# File 'lib/sub_object.rb', line 174

def =~(       *rest); to_source.send(__method__, *rest); end

#inspectString

Returns:

  • (String)


183
184
185
186
# File 'lib/sub_object.rb', line 183

def inspect
  warn_hash
  sprintf('%s[%d,%d]%s', self.class.name.split(/::/)[-1], @pos, @isize, @source[@pos, @isize].inspect)
end

#inspect_before_sub_objectObject



180
# File 'lib/sub_object.rb', line 180

alias_method :inspect_before_sub_object, :inspect

#is_a?(*rest) ⇒ Boolean

Redefining a method in Object to evaluate via #to_source

Returns:

  • (Boolean)


170
# File 'lib/sub_object.rb', line 170

def is_a?(    *rest); to_source.send(__method__, *rest); end

#kind_of?(*rest) ⇒ Boolean

Redefining a method in Object to evaluate via #to_source

Returns:

  • (Boolean)


172
# File 'lib/sub_object.rb', line 172

def kind_of?(*rest); to_source.send(__method__, *rest); end

#pos_sizeAray

Returns:

  • (Aray)


117
118
119
# File 'lib/sub_object.rb', line 117

def pos_size
  [@pos, @isize]
end

#respond_to_missing?(method_name, *rest) ⇒ Boolean

Obligatory redefinition, following redefined #method_missing

Returns:

  • (Boolean)


197
198
199
# File 'lib/sub_object.rb', line 197

def respond_to_missing?(method_name, *rest)
  destructive_method?(method_name) ? super : to_source.send(:respond_to?, method_name, *rest)
end

#sourceObject

Frozen String returned.



127
128
129
130
131
132
# File 'lib/sub_object.rb', line 127

def source
  warn_hash
  src = @source.dup
  src.freeze
  src
end

#subsizeObject

Returns usually the size (Integer).

Returns:

  • usually the size (Integer)



122
123
124
# File 'lib/sub_object.rb', line 122

def subsize
  @isize
end

#to_s(*rest) ⇒ Object

Redefining a method in Object to evaluate via #to_source



178
# File 'lib/sub_object.rb', line 178

def to_s(     *rest); to_source.send(__method__, *rest); end

#to_sourceObject

Returns the original representation of the instance as in the source

Each child class should set the constant TO_SOURCE_METHOD appropriately and should alias this method to the method registered to TO_SOURCE_METHOD . For example, for SubString,

TO_SOURCE_METHOD = :to_str
alias_method TO_SOURCE_METHOD, :to_source

Warning: DO NOT OVERWRITE THIS METHOD.

Returns:

  • (Object)


146
147
148
149
# File 'lib/sub_object.rb', line 146

def to_source
  warn_hash
  @source[@pos, @isize].send(to_source_method)
end