|
6. Inheritance
So far we have always been working with the concrete (i.e. most specific type of an object. What about subclassing and interfaces?
To explore this, we will differentiate between different kinds of sensors.
namespace com.db4o.f1.chapter4
{
using System;
public class SensorReadout
{
DateTime _time;
Car _car;
string _description;
public SensorReadout(DateTime time, Car car, string description)
{
_time = time;
_car = car;
_description = description;
}
public Car Car
{
get
{
return _car;
}
}
public DateTime Time
{
get
{
return _time;
}
}
public string Description
{
get
{
return _description;
}
}
override public string ToString()
{
return _car + ":" + _time + " : " + _description;
}
}
}
|
namespace com.db4o.f1.chapter4
{
using System;
public class TemperatureSensorReadout : SensorReadout
{
double _temperature;
public TemperatureSensorReadout(DateTime time, Car car, string description, double temperature)
: base(time, car, description)
{
_temperature = temperature;
}
public double Temperature
{
get
{
return _temperature;
}
}
override public string ToString()
{
return base.ToString() + " temp: " + _temperature;
}
}
}
|
namespace com.db4o.f1.chapter4
{
using System;
public class PressureSensorReadout : SensorReadout
{
double _pressure;
public PressureSensorReadout(DateTime time, Car car, string description, double pressure)
: base(time, car, description)
{
_pressure = pressure;
}
public double Pressure
{
get
{
return _pressure;
}
}
override public string ToString()
{
return base.ToString() + " pressure : " + _pressure;
}
}
}
|
Our car's snapshot mechanism is changed accordingly.
namespace com.db4o.f1.chapter4
{
using System;
using System.Collections;
public class Car
{
string _model;
Pilot _pilot;
IList _history;
public Car(string model)
{
_model = model;
_pilot = null;
_history = new ArrayList();
}
public Pilot Pilot
{
get
{
return _pilot;
}
set
{
_pilot = value;
}
}
public string Model
{
get
{
return _model;
}
}
public SensorReadout[] GetHistory()
{
SensorReadout[] history = new SensorReadout[_history.Count];
_history.CopyTo(history, 0);
return history;
}
public void Snapshot()
{
_history.Add(new TemperatureSensorReadout(DateTime.Now, this, "oil", PollOilTemperature()));
_history.Add(new TemperatureSensorReadout(DateTime.Now, this, "water", PollWaterTemperature()));
_history.Add(new PressureSensorReadout(DateTime.Now, this, "oil", PollOilPressure()));
}
protected double PollOilTemperature()
{
return 0.1*_history.Count;
}
protected double PollWaterTemperature()
{
return 0.2*_history.Count;
}
protected double PollOilPressure()
{
return 0.3*_history.Count;
}
override public string ToString()
{
return _model + "[" + _pilot + "]/" + _history.Count;
}
}
}
|
6.1. Storing
Our setup code has not changed at all, just the internal workings of a snapshot.
[storeFirstCar]
Car car1 = new Car("Ferrari");
Pilot pilot1 = new Pilot("Michael Schumacher", 100);
car1.Pilot = pilot1;
db.set(car1);
|
[storeSecondCar]
Pilot pilot2 = new Pilot("Rubens Barrichello", 99);
Car car2 = new Car("BMW");
car2.Pilot = pilot2;
car2.Snapshot();
car2.Snapshot();
db.set(car2);
|
6.2. Retrieving
db4o will provide us with all objects of the given type. To collect all instances of a given class, no matter whether they are subclass members or direct instances, we just provide a corresponding prototype.
[retrieveTemperatureReadoutsQBE]
SensorReadout proto = new TemperatureSensorReadout(DateTime.MinValue, null, null, 0.0);
ObjectSet result = db.get(proto);
listResult(result);
|
OUTPUT: 4
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : water temp : 0.2
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil temp : 0.0
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : water temp : 0.8
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil temp : 0.30000000000000004
|
|
[retrieveAllSensorReadoutsQBE]
SensorReadout proto = new SensorReadout(DateTime.MinValue, null, null);
ObjectSet result = db.get(proto);
listResult(result);
|
OUTPUT: 6
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : water temp : 0.2
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil temp : 0.0
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil pressure : 0.6
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil pressure : 1.5
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : water temp : 0.8
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil temp : 0.30000000000000004
|
This is one more situation where QBE might not be applicable: What if the given type is an interface or an abstract class? Well, there's a little DWIM trick to the rescue: Class objects receive special handling with QBE.
[retrieveAllSensorReadoutsQBEAlternative]
ObjectSet result = db.get(typeof(SensorReadout));
listResult(result);
|
OUTPUT: 6
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : water temp : 0.2
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil temp : 0.0
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil pressure : 0.6
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil pressure : 1.5
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : water temp : 0.8
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil temp : 0.30000000000000004
|
And of course there's our query API to the rescue.
[retrieveAllSensorReadoutsQuery]
Query query = db.query();
query.constrain(typeof(SensorReadout));
ObjectSet result = query.execute();
listResult(result);
|
OUTPUT: 6
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : water temp : 0.2
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil temp : 0.0
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil pressure : 0.6
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil pressure : 1.5
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : water temp : 0.8
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil temp : 0.30000000000000004
|
This procedure applies to all first class objects. We can simply query for all objects present in the database, for example.
[retrieveAllObjects]
ObjectSet result = db.get(new object());
listResult(result);
|
OUTPUT: 12
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : water temp : 0.2
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil temp : 0.0
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil pressure : 0.6
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil pressure : 1.5
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : water temp : 0.8
BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil temp : 0.30000000000000004
[BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil temp : 0.0, BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : water temp : 0.2, BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil pressure : 0.6, BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil temp : 0.30000000000000004, BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : water temp : 0.8, BMW[Rubens Barrichello/99]/6 : Tue Apr 19 06:05:15 CEST 2005 : oil pressure : 1.5]
[]
BMW[Rubens Barrichello/99]/6
Ferrari[Michael Schumacher/100]/0
Rubens Barrichello/99
Michael Schumacher/100
|
6.3. Updating and deleting
is just the same for all objects, no matter where they are situated in the inheritance tree.
Just like we retrieved all objects from the database above, we can delete all stored objects to prepare for the next chapter.
[deleteAllObjects]
ObjectSet result=db.get(new object());
while (result.hasNext())
{
db.delete(result.next());
}
|
6.4. Conclusion
Now we have covered all basic OO features and the way they are handled by db4o. We will complete the first part of our db4o walkthrough in the
next chapter by looking at deep object graphs, including recursive structures.
6.5. Full source
namespace com.db4o.f1.chapter4
{
using System;
using System.IO;
using com.db4o;
using com.db4o.f1;
using com.db4o.query;
public class InheritanceExample : Util
{
public static void main(string[] args)
{
File.Delete(Util.YapFileName);
ObjectContainer db = Db4o.openFile(Util.YapFileName);
try
{
storeFirstCar(db);
storeSecondCar(db);
retrieveTemperatureReadoutsQBE(db);
retrieveAllSensorReadoutsQBE(db);
retrieveAllSensorReadoutsQBEAlternative(db);
retrieveAllSensorReadoutsQuery(db);
retrieveAllObjects(db);
deleteAllObjects(db);
}
finally
{
db.close();
}
}
public static void storeFirstCar(ObjectContainer db)
{
Car car1 = new Car("Ferrari");
Pilot pilot1 = new Pilot("Michael Schumacher", 100);
car1.Pilot = pilot1;
db.set(car1);
}
public static void storeSecondCar(ObjectContainer db)
{
Pilot pilot2 = new Pilot("Rubens Barrichello", 99);
Car car2 = new Car("BMW");
car2.Pilot = pilot2;
car2.Snapshot();
car2.Snapshot();
db.set(car2);
}
public static void retrieveAllSensorReadoutsQBE(ObjectContainer db)
{
SensorReadout proto = new SensorReadout(DateTime.MinValue, null, null);
ObjectSet result = db.get(proto);
listResult(result);
}
public static void retrieveTemperatureReadoutsQBE(ObjectContainer db)
{
SensorReadout proto = new TemperatureSensorReadout(DateTime.MinValue, null, null, 0.0);
ObjectSet result = db.get(proto);
listResult(result);
}
public static void retrieveAllSensorReadoutsQBEAlternative(ObjectContainer db)
{
ObjectSet result = db.get(typeof(SensorReadout));
listResult(result);
}
public static void retrieveAllSensorReadoutsQuery(ObjectContainer db)
{
Query query = db.query();
query.constrain(typeof(SensorReadout));
ObjectSet result = query.execute();
listResult(result);
}
public static void retrieveAllObjects(ObjectContainer db)
{
ObjectSet result = db.get(new object());
listResult(result);
}
public static void deleteAllObjects(ObjectContainer db)
{
ObjectSet result=db.get(new object());
while (result.hasNext())
{
db.delete(result.next());
}
}
}
}
|
--
generated by Doctor courtesy of db4objecs Inc.