How to break down an array within an superclass object and place array elements into two subclasses objects in Ruby
You can use Enumerable#partition
:
array = [1, 2, 3, 4]
array.partition { |x| x % 2 == 1 }
# => [[1, 3], [2, 4]]
odd, even = array.partition {|x| x % 2 == 1}
odd
# => [1, 3]
even
# => [2, 4]
class One
attr_reader :array
def initialize(array)
@array = array
end
end
class Two < One
attr_reader :array
def initialize
@array = []
end
end
array = [1,2]
a = One.new(array)
b = Two.new
c = Two.new
odd, even = array.partition {|x| x % 2 == 1}
b.array.concat odd
c.array.concat even
b.array
# => [1]
c.array
# => [2]
NOTE: As meagar commented, the problem is not related with inheritance. You don't need to use class here at all.
Iterate through an array of one class object and put those elements into an array belonging to another class object with Ruby.
class One
attr_reader :array
def initialize(array=[])
@array = array
end
def copy(element, location)
if array.include? element
location.array << element
end
end
end
class Two < One
end
array = ["D","E"]
a = One.new(array)
b = Two.new
c = Two.new
a.copy("D", b)
a.copy("NOT EXIST", b)
b.array
#=> ["D"]
How to make array of inherited objects - Java
The problem was that you defined name
and breed
separately in each subclass of Animal
. You need to make name
and breed
instance variables in Animal
. That way, Java knows that every single Animal has a name
and breed
.
public abstract class Animal {
private String name;
private String breed;
public Animal(String name, String breed) {
this.name = name;
this.breed = breed;
}
public getName() { return name; }
public getBreed() { return breed; }
public abstract void moving();
}
public class Dog extends Animal {
public Dog(String name, String breed) {
super(name, breed);
}
@Override
public void moving(){
System.out.print("Walks\n");
}
}
public class Fish extends Animal {
public Fish(String name, String breed) {
super(name, breed);
}
@Override
public void moving(){
System.out.print("Swims\n");
}
}
Now you can print the name
and breed
for any Animal
, whether it's a Dog
or Fish
.
Animal[] arr = new Animal[6];
arr[0] = new Fish("Riby", "Sea Fish");
arr[1] = new Dog("Any", "Great Dane");
arr[2] = new Fish("Ribytsa", "River fish");
arr[3] = new Dog("Jackie", "Pug");
arr[4] = new Fish("Bobi", "Mix");
arr[5] = new Dog("Ruby", "Labrador");
for (Animal a : arr) {
System.out.println(a.getName() + " " + a.getBreed());
a.moving();
}
Look up all descendants of a class in Ruby
Here is an example:
class Parent
def self.descendants
ObjectSpace.each_object(Class).select { |klass| klass < self }
end
end
class Child < Parent
end
class GrandChild < Child
end
puts Parent.descendants
puts Child.descendants
puts Parent.descendants gives you:
GrandChild
Child
puts Child.descendants gives you:
GrandChild
Ruby: kind_of? vs. instance_of? vs. is_a?
kind_of?
and is_a?
are synonymous.
instance_of?
is different from the other two in that it only returns true
if the object is an instance of that exact class, not a subclass.
Example:
"hello".is_a? Object
and"hello".kind_of? Object
returntrue
because"hello"
is aString
andString
is a subclass ofObject
.- However
"hello".instance_of? Object
returnsfalse
.
Ruby Interface, Collection of Objects
I saw that you come from Java world, and I guess you want to bring Java's generics to Ruby. But, at first place, why Java has generics? Let's have a history lesson.
In early Java (before 1.5), there are no generic types, so the programmers have to write code like this:
List list = new ArrayList();
// add some strings to the list
list.add("foo");
list.add("bar");
// we have to iterate over each element as an Object
for (Object obj : list) {
// and then cast it to String
String str = (String) obj;
// in order to call String methods on it.
String uppercased = str.toUpperCase();
// ...
}
This is certainly not DRY. To ease the pain of casting, Java 1.5 introduces generics.
List<String> list = new ArrayList<String>();
// add some strings to the list
list.add("foo");
list.add("bar");
// now we can iterate over the elements as strings
for (String str : list) {
// no more casting, yay!
String uppercased = str.toUpperCase();
// ...
}
But wait, where does the non-generic version go wrong in the first place?
In Java, the variable type determines which methods can be called on the object, not the object itself. If you declare the variable in a more general type (i.e. a superclass), you can't call methods that belongs to a more special type (i.e. a subclass). If you want to call those methods, you have to cast.
But what if the object itself can decide which methods can be called on it? Suddenly generics become useless. Ruby and many many other dynamic languages follow this way. Rubyists call it duck typing - if something walks like a duck and quacks like a duck, it is a duck.
list = ['foo', 'bar']
list.each do |str|
# we don't care what type str is,
# as long as it has the method upcase.
str.upcase if str.respond_to?(:upcase)
end
So rubyists usually don't define container classes, they just use arrays. If type restriction should be applied, they just apply it when the object is added to the array.
list = []
list << something if something.is_a? Portfolio
Another reason to stick to arrays is that arrays have awesome literals like ['foo', 'bar']
and %w(foo bar)
and %i(foo bar)
, which custom container types don't have.
Override append method () of an ActiveRecord property
When you write r.tags << value
you can also see it like this r.tags.<<(value)
. The tags
method will return an instance of Array
and then this will happen: array.<<(value)
the array will receive the <<
method, not the tags
attribute.
You'd have to overwrite the <<
method on Array
.
It'd be best to take a step back up to the r
object and add an add_tags
method to Rule
to implement your proposed logic. What you're asking for is possible but more complicated to implement than this:
module PgTags
def tags=(value)
write_attribute :tags, value.uniq
end
def add_tags(*t)
self.tags = (tags << t).flatten.uniq
end
end
class Rule < ActiveRecord::Base
include PgTags
end
r = Rule.new
r.tags = %w(one two one)
puts r.tags #=> ['one', 'two']
r.tags.add_tags 'one'
r.tags.add_tags 'three'
puts r.tags #=> ['one', 'two', 'three']
The add_tags
method behaves like you'd expect when you used <<
except that it handles the uniq logic and assigning the new value to the rule's own tags
attribute.
Ruby - determining method origins?
Object#method
returns a Method
object giving meta-data about a given method. For example:
> [].method(:length).inspect
=> "#<Method: Array#length>"
> [].method(:max).inspect
=> "#<Method: Array(Enumerable)#max>"
In Ruby 1.8.7 and later, you can use Method#owner
to determine the class or module that defined the method.
To get a list of all the methods with the name of the class or module where they are defined you could do something like the following:
obj.methods.collect {|m| "#{m} defined by #{obj.method(m).owner}"}
Using switch with subclasses?
No, switch only works on numeric values and enums. (In Java 7 it will work on strings too.)
It sounds like you should probably have a method overridden in the different subclasses... or possibly use enums (which can still override methosds).
If that doesn't help, please give more information about what you're trying to do - ideally with an example.
Related Topics
How to Condense Summable Metrics to a Unique Identifier in a Ruby Table
Bind and Destructure Block Arguments
How to Mimic Browser X509 Client Certificate Verification Without Access to Http Layer
Why Doesn't This Code Produce the Desired Result
How to Fix My Cucumber Expectation Error When Polling
How Does Rails Know My Timezone
Find a Unique Element in a Compound Array
Sum of Arrays of Different Size
How to Initialize an Array in One Step Using Ruby
Create a Ruby Method That Accepts a Hash of Parameters
Instagram Ruby Gem - Unable to Reach Callback Url
Managing Conflicting Versions of Ruby Gems
Cannot Require 'Nokogiri' in Rails (But Works in Irb)
Sinatra Doesn't Know This Ditty Even When Default Route Is Implemented with Modular Style
Sending Form Data to Remote Rails Application Using Httparty
Ruby Project Help. Can't Get Saved Instances from Array
How to Set Up These Crud Controller Actions for Has_Many_Polymorphs and an Error