I am trying to learn Smalltalk (Pharo), but since not so many documentaion available I would like to ask for some help.
I have There two classes, CarRental and Car, and a Test class, CarRentalTest.
Now, supporse rental service has a fixednuber of cars.
| carRental |
carRental := CarRental new.
carRental
addCar: Car panda;
addCar: Car panda;
addCar: Car tesla.
self assert: carRental totalCars size = 3
However, my addCar method is red, how can I fix it?
there is a lot of documentation available for pharo:
here some hints:
http://books.pharo.org (I'd recommend start with "Pharo by Example")
http://mooc.pharo.org
this excellent list: https://www.youtube.com/watch?v=0xF4fnGaE2w&list=PLqbtQ7OkSta0ULYAd7Qdxof851ybh-m (based on an old version of Pharo, but everything applies).
Now, about your question, is hard to have an answer, it depends on a lot of things for example: is the container a Set or an OrderedCollection? Car panda answers what? a new instance of Car or always the same?
Your method addCar: is red (note the colon at the end) because you haven't defined it. Let's write it down then:
The class CarRental must have an instance variable which will hold all its cars. Let's say we name it cars.
In the initialize method (instance side) we need to do the following
CarRental >> initialize
super initialize.
cars := OrderedCollection new.
Now, if we create a new instance of CarRental it will have an empty OrderedCollection in its cars ivar.
Now we can add the addCar: method like this
CarRental >> addCar: aCar
cars add: aCar
Finally, make sure that you have something like this
CarRental >> totalCars
^cars size
Review your code and keep trying!
Related
Trying to create an object which is decided #runtime I have a similar situation as:
class ZOO
feature
animals: LINKED_LIST[ANIMAL]
default_create
do
create animals.make
animals.extend(create {LION})
animals.extend(create {SERPENT})
animals.extend(create {BIRD})
end
open
local
l_sector: ZOO_SECTOR[ANIMAL]
do
across
animals as animal
loop
create {ZOO_SECTOR[animal.item.generating_type]} l_sector
end
end
on create {ZOO_SECTOR[animal.item.generating_type]} l_sector the compiler disagrees with me, I tried with l_type: TYPE[ANIMAL] and create {ZOO_SECTOR[l_type]} l_sector which neither works.
Am I obligated to do something like that? which will be for me a contradiction with polymorphism flexibility, I think I'm missing a mecanism/statement
open
local
l_sector: ZOO_SECTOR[ANIMAL]
do
across
animals as animal
loop
if attached {LION} animal.item then
create {ZOO_SECTOR[LION]} l_sector
else if attached {SERPENT} animal.item then
create {ZOO_SECTOR[SERPENT]} l_sector
else
.....
end
end
Eiffel type system relies on the class structure, and the class structure is fixed at compile time. It might be possible to add types dynamically (e.g., it should be possible to come up with a solution using reflection), but this is not directly expressible in the language itself.
If it is allowed for an animal to know its zoo sector, the ZOO_SECTOR types could be encoded directly in the animal class:
class ANIMAL feature ...
sector: ZOO_SECTOR [like Current] do create Result end
end
Due to the use of like Current, there is no need to add any new code in descendants. The loop from the example would become
across
animals as animal
loop
l_sector := animal.item.sector
end
giving ZOO_SECTOR [LION] for an item of type LION, etc.
Can someone please provide some insight as to when to use delegation via DelegateClass (e.g. Seller < DelegateClass(Person)) and when to use class inheritance (e.g. Seller < Person) in ruby?
class Seller < DelegateClass(Person)
def sales
...
end
end
class Seller < Person
def sales
...
end
end
When I was looking over the Ruby on Rails source on Github I found quite a few uses of DelegateClass.
There are a couple of differences that can help provide insight as to which approach to use.
1) You can safely delegate to primitives (e.g. String), but cannot always safely inherit from them
If you're building on top of Hash or String or Fixnum, you're safer using DelegateClass (or another delegator). For more on why, Steve Klabnik's cautioning is a good place to start).
2) DelegateClass makes it easy to “convert” a more general object into a more specific one
This makes it easier to accept an instance of a general object and make it behave in a way that's specific to your implementation:
class Message < DelegateClass(String)
def print
upcase
end
end
# […]
def log(message)
message = Message.new(message) unless message.is_a?(Message)
end
3) A gotcha: DelegateClass subclasses expect an instance of the delegated class as an argument to new
This can make it tricky to “subclass” classes that you're handing to library code. For example, this is a fairly common practice that won't work out of the box with DelegateClass:
class MyLogger < DelegateClass(ActiveSupport::Logger); end
Foo::ThirdParty::Library.configure do |c|
c.logger = MyLogger # no good
end
This doesn't work because our library expects to behave like most loggers and instantiate without arguments. This can be addressed by defining initialize and creating an instance of ActiveSupport::Logger, but probably not the right solution in this case.
delegates model different behaviors of Person based on the context. e.g. the same person could be a seller in one context or a buyer in a different context. Inheritance is more rigid: a Bear and Tiger inherit from Animal, but an instance of Animal would never need to sometimes behave like a Bear and sometimes behave like a Tiger. An instance of a descendent of Animal is either one or the other.
I have tons of different methods in a particular class that all calculate unique instance variables. I've been using the attr_reader to access these without any problem, but now I've got dozens of these and wondering if there's a preferred / eloquent way to access all of these instance variables - not just a solution, but a generally accepted preferred method/style.
I've seen similar questions regarding class level variables, but that's something I'd like to avoid. Maybe I can do this with a Module, but I thought those were for storing piles of constants? But maybe it's something I'm missing with regular Class inheritance? Inheriting self?
If you imagine the pile of these instance variables as mathematical constants (pi, eulers, etc.) that all get a number added to them (depending on user input). I'm aware of classes and methods doing one thing, which the Stack class and method definitely do one thing - they're just storing pieces of data that are needed by many other classes and methods.
An example of code that I'm working with:
class Stack
attr_reader :pi, :euler # ... and dozens more of these
def initialize
#pi = 3.14 + 8
#euler = 0.577 + 8
# dozens more assignements here
end
end
class Overflow
def show
a = Stack.new
p a.pi # attr_reader works fine here
end
end
class AnotherClass
def some_method_that_needs_all_variables_in_Stack
# Do I need to create another instance of the
# Stack class like I did in Overflow?
# or should AnotherClass somehow inherit all the instance variables?
end
end
Overflow.new.show # => 11.14.
Thanks!
Have you heard about Single Responsibility Principle? It says, that 1 class should do only 1 thing, but do it well. Having a hundred (man, even five of them should make you doubt if your code is good) of instance variables, means that you have an antipode: God object, that does everything. This code is very hard to change because of myriad of hidden dependencies between method calls and instance variables.
The solution: Move out new classes and make them talk to each other. Read some book on the Object Oriented Programming, there are tons of them, and you'll immediately start feeling better about your code.
If I have a class Salad with a method chew and I use super in it, it will call the next available chew method available going up the chain of ancestors. What if I want to "reach two levels up" (to the second available chew method going up the chain)? Is there any way to do that without adding super to the first ancestor's method?
To make this a little more concrete, suppose this is my Salad class, with a salad object:
class Salad < Food
include Almonds
include Gorgonzola
include Spinach
include Dressing
def chew
super
end
end
salad = Salad.new
The array of the ancestors would be like this:
[Salad, Dressing, Spinach, Gorgonzola, Almonds, Food, Object, Kernel, BasicObject]
If I want salad.chew to trigger the chew method in Spinach without adding super to Dressing#chew, is that possible? Is there a way to reach two levels up (in the same way that super "reaches" one level up)?
Yes, there is a way to do what you are describing, and that way is through methods #method and #instance_method, as in method = Spinach.instance_method( :chew ), which you can then bind to Salad, or to metaclasses of Salad instances, as in method.bind( Salad ). This mechanism is not as neat as using the convenience keyword super, but offers a superset of super's functionality. There are a few more details, but trust me, this way, you can do anything you want. That's the power of Ruby – you can do anything, up to the point that for the Lispiest magic, you need Ripper, and (the thus far unfinished) Sorcerer.
(For a usage example, see my other answer at Using the Object.inspect / Object.to_s on a class derived from Hash)
No, there's no way to do what you are describing (and for good reason). Any use of the "super-super" keyword which you describe would be too tightly coupled to the details of your inheritance chain (and which classes/modules in that chain implement a given method). It would be very brittle; if such a keyword existed, and you used it, then small changes like moving a method definition would very easily break things. It would also be very confusing for readers of your code.
The purpose of the super keyword is: you can take a class, subclass it, override a method, and add some new behaviors to that method, while still doing everything that the method originally did. super effectively says: "now perform the default behavior for this method". That works regardless of whether that "default" behavior is defined in the superclass, super-superclass, a module, or anywhere else.
If you are wondering how to achieve calling the chew method on all the modules, there is a better solution that is using composition. Modules are for behavior and if you think about your Salad class, you don't want it to behave like a Spinach or Almonds, you want it to be composed of them. So when you chew a salad you chew each of its components.
Ruby Newbie here,
I understand that everything is an object in Ruby, one thing that I wasn't sure about was understanding Variables. Variables basically give reference to objects (correct me if I'm wrong). During an instructional video, the teacher did a demonstration which went as below:
(irb)
a = 100
==> 100
b = a
==> 100
b
==> 100
This part I get, makes total sense.
Then he did
a = 50
==> 50
b
==> 100
If B is supposed to point to what a was set which was a 100, why does b still point to 100 if a has now been set as 50?
Here's the cool thing, 100 is an object too. So a pointed to the constant object 100 and when you assigned b = a you assigned b to the pointer to the object 100 not to the pointer for a or even a value of 100 held by a.
To see this is true try this:
irb> puts 100.object_id
=> 201
Cool huh?
Here's a little explanation of the Ruby object model I wrote up a while back. It's not specific to your question but adds a little more knowledge on how the Ruby object model works:
When you create an instance of an object what you have created is a new object with a set of instance variables and a pointer to the class of the object (and a few other things like an object ID and a pointer to the superclass) but the methods themselves are not in the instance of the object. The class definition contains the list of methods and their code (and a pointer to its own class, a pointer to its superclass, and an object ID).
When you call a method on an instance Ruby looks up the class of the instance and looks in that class's method list for the method you called. If it doesn't find it then it looks in the class' superclass. If it doesn't find it there it looks in that class' superclass until it runs out of superclasses. Then it goes back to the first class and looks for a method_missing method. If it doesn't find one it goes to the superclass and so on till it gets to the root object where it's designed to raise an error.
Let's say for instance you have a class Person and you make an instance of the class with the variable bubba like this:
class Person
attr_accessor :dob, :name
def age
years = Time.now.year - #dob.year
puts "You are #{years} year#{"s" if years != 1} old"
end
def feed
puts "nom, nom, nom"
end
end
bubba = Person.new
bubba.name = "Bubba"
bubba.dob = Time.new(1983,9,26)
The class diagram would look something like this:
So what's happening when you create a static method, a class/module method? Well, remember that almost everything is an object in Ruby and a module definition is an instance of the class Class. Yep, that code you type out is actually an instance too, it's live code. When you create a class method by using def self.method_name you are creating a method in the instance of the object that is the class/module definition.
Great, so where's that class method being defined at you ask? It's being defined in an anonymous class (aka singleton, eigen, ghost class) that is created for exactly this reason.
Going back to our Person class what if we add a class method on the instance bubba like so:
def bubba.drive_pickup
puts "Yee-haw!"
end
That method gets put into a special singleton class created just for that instance and the singleton's superclass is now the Person class. This makes our method calling chain look like this:
Any other methods defined on the instance object bubba will also be put into that singleton class. There's never more than one singleton class per instance object.
So, to wrap it all up the reason why it doesn't work is the static methods in the modules are being defined in the singleton class for the instance of the module definition. When you include or extend from the module you are adding a pointer to the method table of the module but not the method table of the instance object of the singleton class for the module.
Think of it this way: If you create an instance x of type Z and an instance y of type Z should x know about y? No, not unless specifically told about it. So too your module that mixes in another module should not know about some other object that just happens to have that first module as its superclass.
For a much better explanation of the Ruby object model watch this awesome free video by the amazingly erudite Dave Thomas (no, not the guy from Wendy's):
http://scotland-on-rails.s3.amazonaws.com/2A04_DaveThomas-SOR.mp4
After watching that video I bought Dave Thomas's whole series on the Ruby object model from Pragmatic and it was well worth it.
P.S. Anyone please feel free to correct me on anything I forgot; like what's specifically in an object.
b = a does not mean: b equals a. It means : let b refer to the same object that a is referring to now.
If you later decide to refer a to another object
a=50
then b still refers to the old object.
It's like you have a dog and decide to name it Charles (Charles = a Dog). Later on, you also use the name Charlie for the dog. (Charlie = Charles). The dog doesn't mind how many names refer to him, it's the same old dog.
Still later you get a goldfish and you decide Charles is a much better name for a goldfish than for a dog (Charles = a Goldfish). In Ruby, the dog is now still named Charlie.
Mind you, if the dog has no name at all, he'll get garbage collected eventually.
Remember that variables refer to (or hold) values, not references to other variables. So when you assign b = a you're saying "let b hold the value that a currently holds". So "a" and "b" are separate variables that happen to hold the same reference. You can change either one without affecting the other.