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 : Thu Mar 17 15:15:18 CET 2005 : oil temp : 0.0
    BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : water temp : 0.8
    BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil temp : 0.30000000000000004
    BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : water temp : 0.2



[retrieveAllSensorReadoutsQBE]
SensorReadout proto = new SensorReadout(DateTime.MinValue, null, null);
    ObjectSet result = db.get(proto);
    listResult(result);
OUTPUT:
6
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil temp : 0.0
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil pressure : 1.5
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : water temp : 0.8
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil temp : 0.30000000000000004
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil pressure : 0.6
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : water temp : 0.2


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 : Thu Mar 17 15:15:18 CET 2005 : oil temp : 0.0
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil pressure : 1.5
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : water temp : 0.8
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil temp : 0.30000000000000004
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil pressure : 0.6
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : water temp : 0.2


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 : Thu Mar 17 15:15:18 CET 2005 : oil temp : 0.0
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil pressure : 1.5
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : water temp : 0.8
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil temp : 0.30000000000000004
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil pressure : 0.6
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : water temp : 0.2


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:
13
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil temp : 0.0
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil pressure : 1.5
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : water temp : 0.8
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil temp : 0.30000000000000004
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil pressure : 0.6
BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : water temp : 0.2
Db4oDatabase: [B@d4ddfd
[]
[BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil temp : 0.0, BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : water temp : 0.2, BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil pressure : 0.6, BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : oil temp : 0.30000000000000004, BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 2005 : water temp : 0.8, BMW[Rubens Barrichello/99]/6 : Thu Mar 17 15:15:18 CET 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());
    }
OUTPUT:



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.