Instead of classes lets think about real things.
say you have the concept of a Pet, and lets say that all have pets have a name. Now lets say you have the the concept of PetDog, which like all pets has a name, but also has a "breed".
As you can see its perfectly reasonable to think of a PetDog, as both a Pet (its superclass) and as a PetDog (a subclass of Pets)
More mathematically you can think of a class a set of all objects with some similar characteristic, and then the subclass "surrounds" the superclass and has even more characteristics.
class Food
attr_accessor :name
end
class Fruit < Food
attr_accessor :ripeness
end
banana = Fruit.new
banana.ripeness = 0 # very green banana
banana.name = "banana"
steak = Food.new
steak.ripeness = 3 # ERROR... the base class Food does not know about "ripeness"
How about a real (working) example? Lets use the react.rb DSL to define a Clock and Alarm UI components
The Clock component class is subclass of React::Component::Base so gets a lot "state" that is part of the base class. It knows how to render to html, it knows how to react when things update, etc. This all part of the base class, and all the data to control that and make it work stays in the base class.
In addition Clock ihas some special properties, i.e. it keeps track of the current time in the @clock variable. It also updates itself every second.
Then we make a subclass of that, called Alarm.
Because an Alarm is a subclass of Clock it has that internal @clock variable (which is actually part of the clock class), and like any other Clock, Alarms update themselves every second. This is important! Notice that it is the Clock class that initializes the @clock variable, and it is also the Clock class that uses the clock to update (redisplay) itself. When Alarm inherits from Clock, the @clock variable must stay part of clock so that it behaves properly.
But in addition Alarm uses the @clock variable for its own purpose namely to check and see if "times up", and when it is up, it nicely stops the clock from running (notice that even after the alert is displayed, the Clock keeps running but the Alarm does not.
Hope this helps - make sure to run the example!
<div id="container"></div>
<script type="text/ruby">
class Clock < React::Component::Base
# a component that displays the time
after_mount do
@clock = every(1) { force_update! }
end
def render
"#{Time.now}"
end
end
class Alarm < Clock
# a kind of clock that notifies its caller when time is up!
param :at, type: Time
param :notify, type: Proc
before_update do
# before_update is a feature of React::Component::Base
# the following code is executed before each update of the Alarm
if Time.now > params.at
params.notify
@clock.stop
end
end
def render
"Alarm will go off in #{(params.at-Time.now).to_i} seconds"
end
end
Element['#container'].render do
div do
# This is react.rb's way of creating a new instance of Clock
# Its shorthand for doing a Clock.new() and a bunch of other stuff
Clock()
br
Alarm(
at: Time.now+10.seconds,
notify: -> { alert ('beep beep beep') }
)
end
end
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/reactive-ruby/inline-reactive-ruby/master/inline-reactive-ruby.js"></script>