| # 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 : Wed Jan 25 22:22:15 CET 2006 : water temp : 0.2 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : oil temp : 0.0 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : water temp : 0.8 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : 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 : Wed Jan 25 22:22:15 CET 2006 : water temp : 0.2 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : oil temp : 0.0 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : oil pressure : 0.6 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : oil pressure : 1.5 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : water temp : 0.8 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : 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 trick to keep in mind: Type objects receive special handling with QBE.

`[retrieveAllSensorReadoutsQBEAlternative] ObjectSet result = db.get(typeof(SensorReadout)); listResult(result);`

OUTPUT: 6 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : water temp : 0.2 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : oil temp : 0.0 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : oil pressure : 0.6 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : oil pressure : 1.5 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : water temp : 0.8 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : oil temp : 0.30000000000000004

And of course there's our SODA API:

`[retrieveAllSensorReadoutsQuery] Query query = db.query(); query.constrain(typeof(SensorReadout)); ObjectSet result = query.execute(); listResult(result);`

OUTPUT: 6 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : water temp : 0.2 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : oil temp : 0.0 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : oil pressure : 0.6 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : oil pressure : 1.5 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : water temp : 0.8 BMW[Rubens Barrichello/99]/6 : Wed Jan 25 22:22:15 CET 2006 : oil temp : 0.30000000000000004

## 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.

`[deleteAll] ObjectSet result = db.get(typeof(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); } 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); } } }`

--
generated by Doctor courtesy of db4objects Inc.