Inheritance
Perhaps Ferret's most unique feature is its ISA inheritance system. The name
ISA is borrowed from Perl, where package variables @ISA
consist of parent
package names. However, Ferret's inheritance system is quite different.
Ferret objects do not inherit from classes; they inherit from other objects. As silly as it may sound, objects can belong to any number of classes. But they don't inherit from those classes; they inherit from their prototype objects.
If an object is an instance of the String class, for instance, its *ISA
(list of parent objects) would include the String.proto
object.
Example class
Below is an example of a Ferret class from the standard library.
package Math class Point init { need @x: Num, @y: Num } .distanceTo { need $pt2: Point $dx = @x - $pt2.x $dy = @y - $pt2.y -> sqrt($dx ^ 2 + $dy ^ 2) } .distanceFromOrigin -> @distanceTo(*class(0, 0)) .pretty -> "(@x, @y)" .toString -> @pretty .description -> "Point" + @pretty func midpoint { need $pt1: Point, $pt2: Point -> *class( x: ($pt1.x + $pt2.x) / 2, y: ($pt1.y + $pt2.y) / 2 ) } func distanceBetween { need $pt1: Point, $pt2: Point -> $pt1.distanceTo($pt2) }
Initializing an object as a certain type is as simple as adding an object to
its *ISA
list. However, this is not typically done directly. Consider this
example.
# Create an empty object. This is like {} in JavaScript. $obj = (:) # Make the object an instance of Point. Math::Point.init($obj)(0, 0) # The object is now a Point representing the origin. # Therefore, $obj.*ISA includes Math::Point.proto. inspect($obj)
Output
[ Point ]( x = 0 y = 0 )
This is equivalent to below, as calling a class creates an empty object and initializes it in one step.
$obj = Math::Point(0, 0)
Example of basic inheritance
Because Ferret objects can inherit from any objects, a class is not required for inheritance. Below is an example of basic inheritance without a class.
# create a basic object representing a male being. $male = (gender: "male") # create a basic object representing a specific person. $person = (name: "Jake", age: 22) # add $male to $person's *ISA list $person.*ISA.push($male) inspect($person)
Output
[ Object ]( age = 22 name = "Jake" (gender) = "male" )