Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
109 views
in Technique[技术] by (71.8m points)

c# - Call function based on instance type not working as I expect

Problem


Currently I'm trying to write some inventory system. The inventory contains several items. The functionality of each item will changed based on the dog it's used on. Most of the time this means it will do nothing, but specific dogs can use specific items.

I figured I would write a base Item class that implements a generic use(Dog dog) function. Then if a specific item wants to apply a certain functionality for a dog, it could override the function with a more specific dog type. For example TennisBall : Item has a use(GoldenRetriever dog). However, having written this it appears as if only the parent function is ever called.

In my Inventory class I have a reference to the dog based on the Dog class. When I log what the type of this Dog is, I get GoldenRetriever. Yet still the parent Item.use() function is called instead of the more concrete TennisBall.use() function. The reason for this is probably that Dog is what the instance is cast to, so it will call that (not quite sure why my Debug.Log still shows GoldenRetriever then).

I've tried specifying some interfaces to solve the problem also, but it seems that the problem persists. My feeling is that this rather has to do with the parameters in the methods than with anything else.

Question


How can I define functions for my derived classes so they are called based on the type of the provided instance? Do I *have* to cast my instance to a specific type? I find this unintuitive since C# already seems to know what the type of the instance is.

Code


Inventory:
public class Inventory : MonoBehaviour {
    ...
    
    private List<Item> items = new List<Item>();
    private Dog dog;
    public int activeItem = 0;

    ...

    public void addItem(Item item) {        
        items.Add(item);  // This is where the TennisBall item will be added
    }

    public void open(Dog dog) {
        open();
        this.dog = dog;
    }

    void Update() {
        if (Input.GetKeyDown(KeyCode.E)) {
            Debug.Log(dog);  // Output: Golden Retriever (GoldenRetriever)
            items[activeItem].use(dog);
        }
    }
}

Item:

public class Item : MonoBehaviour {
    public void use(Dog dog) {
        Debug.Log(dog);  // Still Golden Retriever (GoldenRetriever)
        throw new NotImplementedException();
    }
}

TennisBall:

public class TennisBall : Item {
    public void use(GoldenRetriever dog) {
        Debug.Log("Doing something specifically for a Golden Retriever!");  // This never gets called
    }
}
question from:https://stackoverflow.com/questions/65875572/call-function-based-on-instance-type-not-working-as-i-expect

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You can start with actually overriding the use function and using some type-testing in the override:

public class Item : MonoBehaviour {
    public vitual void use(Dog dog) {
        Debug.Log(dog);  // Still Golden Retriever (GoldenRetriever)
        throw new NotImplementedException();
    }
}

public class TennisBall : Item {
    public override void use(Dog dog) {
         var goldenRetriever = dog as GoldenRetriever; // check if dog is of type GoldenRetriever
         if(goldenRetriever != null)
         {
              Debug.Log("Doing something specifically for a Golden Retriever!");  // This never gets called
         }
         // your other logic....       
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...