How to Break Down an Array Within an Superclass Object and Place Array Elements into Two Subclasses Objects in Ruby

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 return true because "hello" is a String and String is a subclass of Object.
  • However "hello".instance_of? Object returns false.

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



Leave a reply



Submit