I'm having issues understanding this encapsulation. I have instance variables defined with attr_accessor. I'm trying to access them outside class. But they are always nil and returns undefined method.
NoMethodError: undefined method `has_key?' for nil:NilClass
Please help me understand.
class TrieNode
attr_reader :value, :next, :children
def initalize
#value = nil
#children = Hash.new
#next = nil
end
end
class Trie
attr_accessor :root
def initialize
#root = TrieNode.new
end
def build_trie(strs)
cur = #root
strs.each do |str|
str.chars.each do |char|
if cur.children.has_key? char
cur = cur.children[char]
next
else
new_node = TrieNode.new
cur.children[char] = new_node
cur = new_node
end
end
cur = #root
end
end
end
Yes, it is not encapsulation, it is because your object is not instantiated properly, which is caused by a typo
def initalize
#value = nil
#children = Hash.new
#next = nil
end
should be initialize not initalize
Related
I am trying to print a linked list in ruby but getting the error add': undefined method `next=' for #<Node:0x000001c5c0738688 #data=1, #next=nil> (NoMethodError)
any idea what i should do ?
class Node
def initialize data
#data = data
#next = nil
end
end
class LinkedList
def initialize
#head = nil
end
def add data
temp = #head
#head = Node.new(data)
#head.next = temp
end
def printList
temp = #head
while temp
puts temp.data
temp = temp.next
end
end
end
list = LinkedList.new
list.add(1)
list.add(2)
list.add(3)
list.printList()
In order to access the setter for the next attribute I'd propose adding an attribute_accessor to Node.
class Node
attr_accessor :next
def initialize(data)
#data = data
end
end
This will generate both a setter and a getter for the next attribute within your Node instance.
Additionally I would also add an attr_reader to Node so that you can access data from outside of the instance.
class Node
attr_accessor :next
attr_reader :data
def initialize(data)
#data = data
end
end
If the argument "entry" to the method add is a hash I need to add it to the :entries hash. If "entry" is a string "entry" needs to be set as a key in the hash and its value to nil. I have a solution below but is there a cleaner way to do this?
class Test
attr_accessor :entries
def initialize
#entries = {}
end
def add(entry)
if entry.is_a?(Hash)
entry.each do |word, definition|
#entries[word] = definition
end
else
#entries[entry] = nil
end
end
end
#test = Test.new
#test.add("the")
#{"the" => nil}
#test.add("the" => "one")
#{"the"=>"one"}
I refactored the code:
class Test
attr_accessor :entries
def initialize
#entries = {}
end
def add(entry)
entry.is_a?(Hash) ? #entries.merge!(entry) : #entries[entry] = nil
end
end
I have the following code, and was wondering if someone can tell me why, after running it, the value of #left_child and #right_child are still nil.
I think I know why, but I am asking for confirmation to the community. Also, is there a way I can make this work in a way like this?
module BinaryTree
class Node
attr_accessor :left_child, :right_child
def initialize(value)
#value = value
#left_child = nil
#right_child = nil
end
def add_child(value)
if value > #value
create_child(value, #right_child)
else
create_child(value, #left_child)
end
end
private
def create_child(value, which_child)
if which_child.nil?
which_child = Node.new(value)
else
which_child.add_child(value)
end
end
end
end
node = BinaryTree::Node.new(50)
node.add_child(20)
node.left_child # => nil
node.add_child(70)
node.right_child # => nil
They are still nil because you've never assign values to them. Instead, you should change to this:
module BinaryTree
class Node
attr_accessor :left_child, :right_child
def initialize(value)
#value = value
#left_child = nil
#right_child = nil
end
def add_child(value)
if value > #value
#right_child = create_child(value, #right_child)
else
#left_child = create_child(value, #left_child)
end
end
private
def create_child(value, which_child)
if which_child.nil?
which_child = Node.new(value)
else
which_child.add_child(value)
end
which_child
end
end
end
which_child is a variable local to create_child. The value of #right_child is being copied to it when you call the method. Your code is basically the same as
right_child = nil
which_child = right_child
which_child = true
# right_child is still nil!
Variables in Ruby store pointers to objects, and Ruby passes around those pointers by value. See also:
Ruby - Parameters by reference or by value?
Is Ruby pass by reference or by value?
I got a question for implementation methods like get_item(index), or find(value) with used classes.
class SinglyLinkedListItem
attr_accessor :object, :next
attr_reader :list
def initialize(object, list)
#object = object
#list = list
end
end
class SinglyLinkedList
attr_reader :length
def initialize
#length = 0
#head = nil
#tail = nil
end
got some methods like
def each
if #length > 0
item = #head
begin
yield item.object
item = item.next
end until item.nil?
end
end
I tried with many ways, but im still getting this error:
NoMethodError: undefined method `object' for nil:NilClass
You have to define method #object on nil:
def nil.object; self end
The error will not appear that way.
I had this problem before with attr_accessor.
Try replacing the
##
with
self.#
And you might want to check the item class as a precaution.
yield item.object unless item.nil?
For Ex:
def each
if self.length > 0
item = self.head
begin
yield item.object unless item.nil? #Check if item turned nil or not
item = item.next
end until item.nil?
end
end
And there might be some more handling that you need to do, but your given data doesn't provide me enough information.
New to Ruby. Receiving error: undefined method `+' for nil:NilClass (NoMethodError)
I do not understand why I am receiving an error for such a simple task of incrementing a value. However, perhaps the error is caused by something else.
What is the cause?
class LinkedList
class Node
attr_accessor :data, :nextNode
def initialize(data = nil, nextNode = nil)
#data = data
#nextNode = nextNode
end
end
#member variables
#head = nil
#size = 0
def initialize
#head = Node.new()
end
def add(val)
curr = #head
while curr.nextNode != nil
curr = curr.nextNode
end
curr.nextNode = Node.new(val)
#size += 1 #<<<-------------------------------------ERROR LINE----------
end
end
list = LinkedList.new()
list.add(0)
Move the declaration for #size into the initialize method:
def initialize(data = nil, nextNode = nil)
#data = data
#nextNode = nextNode
#size = 0
end