Search Unity

Fetching a reference to an extended script

Discussion in 'Scripting' started by Marscaleb, May 23, 2021.

  1. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    1,037
    I have a variable that is set as a reference to a particular script.
    At a certain point in my code this reference could only be a particular class which is an extension of that class.
    e.g.
    class PepperoniPizza : Pizza
    and my variable is
    protected Pizza ThisPizzaRightHere


    How do I get this reference variable to be treated like the extended class so I can access functions and stuff from the extended class?
    Right now I declare a new variable of the extended class and use my existing variable to go to it's game object and then getComponent of the extended class. There's gotta be a simpler way.

    I tried looking it up but I don't know the specific terms, and I can only find tutorials trying to explain what extending a class is.
     
  2. You don't. It is important to not to do that, inheritance in this context is to treat any child classes like the parent class, not the other way around. Use interface instead where you can add any kind of behavior to any kind of class on any level.
     
    Vryken and Kurt-Dekker like this.
  3. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    @Lurking-Ninja is correct, but there's a lot of things in gamedev you shouldn't do code wise. ;)

    You can cast to the derived type and use that instead.

    Code (csharp):
    1.  
    2. PepperoniPizza pizza = ThisPizzaRightHere as PepperoniPizza;
    3.  
    4. if(pizza != null)
    5. {
    6.     // it was pepperoni after all
    7. }
    8.  
     
  4. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,991
    Well, that's not necessarily true. Yes you're totally right that when you apply the concept of abstraction the point is that you do not need to know what exact object you're dealing with. Though there are cases where it may be necessary to know what exact type you're dealing with. You can not cover all possibilities in an abstract and generic way. So you may need an upcast from time to time. However an upcast should only be combined with either a type check or other reliable information that tells you about the actual type.

    Casting can be performed in many different ways. The fastest way is to just use the normal c-style cast

    Code (CSharp):
    1. PepperoniPizza pepperoniPizza = (PepperoniPizza)ThisPizzaRightHere;
    However this cast will throw an InvalidCastExcpetion if the cast is not possible. So when using this type of cast you should be 100% sure that the object referenced is indeed a PepperoniPizza.

    Next there's the as-cast as @GroZZleR has shown. The as-cast only works with reference types and it does not throw an exception when the cast fails. Instead it simply returns null. The as cast should only ever be used in conjunction with a null check.

    In the latest C# we got a new feature (can't remember which C# version it was introduced) that allows you to declare local variables inside an if-statement. While in the past the "is" operator could only be used to check the type of a reference, it can now be used to perform an inplace cast which is really useful when doing if-else chains. So you can do

    Code (CSharp):
    1. if (ThisPizzaRightHere is PepperoniPizza pepperoniPizza)
    2. {
    3.  
    4. }
    5. else if (ThisPizzaRightHere is SomeOtherPizza someOtherPizza)
    6. {
    7.  
    8. }
    This has the advantage that the local variable is only visible inside the scope of the if statement it belongs to.

    All that's being said, when you use polymorphism and inheritance, you usually want to abstract the functionality so each class is responsible for dealing with its own oddities so that there is no need to know the actual type. That's what abstract and virtual methods are good for. Inheritance without virtual or abstract methods is kinda pointless.

    You haven't said how or for what reason you need to access the specific type of Pizza. It would be great if you could give a more specific example and what problem you want to solve. There are always multiple ways to solve the same issues. However some solutions are considered bad practise any may have better solutions available. However in order to suggest alternatives we need to know more about the actual problem.
     
    Lurking-Ninja and Vryken like this.
  5. That's the thing. If I need to know if my pizza is spicy or not, I did it wrong. I did the wrong abstraction. I won't start casting my >Pizza< objects into JalapenoPizza and HabaneroPizza... I restructure it into an interface and I handle ISpicyPizza instead. I know dumb example, but I'm just in the middle of my morning coffee... sorry :D.