Why interface name needs to be declared in front of function for ISaveable

I still dont fully understand why the class name needs to be put in front of function for CaptureState() and RestoreState()

object ISaveable.CaptureState()
        {
            var slotRecords = new InventorySlotRecord[inventorySize];
            for (int i = 0; i < inventorySize; i++)
            {
                if (slots[i].item != null)
                {
                    slotRecords[i].itemID = slots[i].item.GetItemID();
                    slotRecords[i].quantity = slots[i].quantity;
                }
            }
            return slotRecords;
        }

Instead of simply declaring the function as object CaptureState() or void RestoreState()?

TL;DR
It doesn’t have to be there. It’s a way for us to ‘hide’ interface members.

What we are doing here is creating ‘Explicit Implementations’. When we implement an interface, all the members on that interface must be public but we don’t necessarily want that to be the case. We don’t really want to expose CaptureState and RestoreState to the rest of the system so, to do that, we implement these interface members as ‘explicit’.

But what does that mean? Well, it means that these methods will not be visible on the class. The only way these methods can be called is through an ‘interface reference’ (I think this is my own terminology). The saving system gets all ISaveable classes. In some sense it doesn’t get class references, it gets the ‘interface references’. So, it gets the classes but it knows nothing about them other than the fact that they implement the interface. The only methods you will see on any of the classes at this point is the interface methods (and perhaps some intrinsic methods and extension methods for the interface). Because it is an ‘interface reference’ and we defined these methods as ‘explicit’, these two methods are now public and visible and can be called from outside the class.

A small bit of code may explain it a little better

interface ISample
{
    void Test();
    void AnotherTest();
}
class Sample : ISample
{
    void ISample.Test() // notice there's no access modifier here
    {
        // test stuff
    }

    public void AnotherTest() // normal way of implementing the interface
    {
        // more test stuff
    }

    public void ClassTest() // This is only on the class, not in the interface
    {
        // class test stuff
    }
}
class Consumer
{
    public void ConsumeClass(Sample classRef)
    {
        classRef.Test(); // will fail because there is no 'Test' in the class reference
        classRef.AnotherTest(); // will succeed because interface members must be public
        classRef.ClassTest(); // will succeed because it's on the class and public
    }
    public void ConsumeInterface(ISample interfaceRef)
    {
        interfaceRef.Test(); // will succeed because there is a 'Test' in the interface reference
        interfaceRef.AnotherTest(); // will succeed because it's on the interface
        interfaceRef.ClassTest(); // will fail because we don't know anything about the class
    }
}

I hope this makes sense. I tried to explain it as simply as possible. Feel free to ask if there’s anything I need to clarify

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms