Home > Net >  C# Populate ObjectB field by operating on its parent without type checking
C# Populate ObjectB field by operating on its parent without type checking

Time:10-16

Object X has some data that Object B is interested in but it operates on its parent (Object A). Object B declares a field that isn't declared in object A. Object C is also a child of Object A but it doesn't declare that field that object B does.

How to populate object B field? (is type checking and casting really the only solution?)

EDIT (Added an example)

public class ObjectX
{
    // eventually interested by ObjectB
    public float time;
    
    private ObjectA _objectAOrBStoredInAReference;

    public ObjectX(ObjectA objectAOrB)
    {
        this._objectAOrBStoredInAReference = objectAOrB;
    }

    public void PassTimeToObjectB()
    {
        // need to pass the time to ObjectB since it is interested in this
    }

    public void SomeStuffToDo()
    {
        PassTimeToObjectB();
        _objectAOrBStoredInAReference.StuffToDo();
    }

    public abstract class ObjectA
    {
        public abstract void StuffToDo();
    }
    
    public class ObjectB : ObjectA
    {
        public float time;

        public void SetTime(float time)
        {
            this.time = time;
        }

        public override void StuffToDo()
        {
            // Using Populated time here
        }
    }
}

CodePudding user response:

I can see a couple of solutions here:

1: Only ObjectX knows the time

If the time is such that only ObjectX can possibly know it, then you can pass ObjectX as an argument to StuffToDo:

public class ObjectX
{
    // eventually interested by ObjectB
    private float time;

    // Expose 'time' as a readonly property - I'm assuming
    // other classes shouldn't need to manipulate it?
    public float Time => time;

    private ObjectA _objectAOrBStoredInAReference;

    public ObjectX(ObjectA objectAOrB)
    {
        this._objectAOrBStoredInAReference = objectAOrB;
    }

    public void SomeStuffToDo()
    {
        // Don't need to set the time anymore - 
        // ObjectB can retrieve the time itself.
        _objectAOrBStoredInAReference.StuffToDo(this);
    }
}

public class ObjectB : ObjectA
{
    // REMOVE ALL THIS CODE - NOT NEEDED ANYMORE
    //public float time;

    //public void SetTime(float time)
    //{
    //   this.time = time;
    //}

    public override void StuffToDo(ObjectX x)
    {
        var time = x.Time;
        // Do stuff involving 'time'.
    }
}

2: The time can be known solution-wide:

If the time is just a general time that is not specific to ObjectX then expose it via it's own type ITimeProvider:

public interface ITimeProvider
{
    float Time { get;}
}

public class ObjectX
{
    // Remove any 'time' related stuff from X
    private ObjectA _objectAOrBStoredInAReference;

    public ObjectX(ObjectA objectAOrB)
    {
        this._objectAOrBStoredInAReference = objectAOrB;
    }

    public void SomeStuffToDo()
    {
        _objectAOrBStoredInAReference.StuffToDo();
    }
}

public class ObjectB : ObjectA
{
    private readonly ITimeProvider _timeProvider;
    public ObjectB(ITimeProvider timeProvider)
    {
        this._timeProvider = timeProvider;
    }
 
    public override void StuffToDo(ObjectX x)
    {
        var time = _timeProvider.Time;
        // Do stuff involving 'time'.
    }
}
  • Related