- Home /
Can I override a variable type
I'm trying to adapt a script from an asset, it has a Text variable, I use TMPro, so the easy way would be opening the script and replacing every Text by TextMeshProUGUI, but I want to be organized and override methods so I can update the other scripts, i know about overriding methods but i don't know how to change existing variable types, so other methods and other scripts can still access them.
public class MMAchievementDisplayItem : MonoBehaviour
{
public Image BackgroundLocked;
public Image BackgroundUnlocked;
public Image Icon;
public Text Title;
public Text Description;
public MMProgressBar ProgressBarDisplay;
}
This is my override Script:
public class SSAchievementDisplayItem : MMAchievementDisplayItem {
public new TextMeshProUGUI Title;
public new TextMeshProUGUI Description;
}
But I get an error saying theres multiple instantiations of the same variable and that is not supported:
You can't change the type of a variable declared in your parent class. You are simply hiding it for the instances of your subclass. However because of the way unity's serializer works it still considers all your parent class variables for serialization.
What you can do is override the methods that use this Text variables and make them use Text$$anonymous$$eshProUGUI, depending on the size and complexity of the class it can be easy or not.
This together with a custom inspector for your new class you could hide the unused Title and Description variables and have a working script.
I ended up just making new variables and overriding the methods that used the old ones to use the new ones, I knew this was a solution but I was afraid other scripts that depended on those old variables would have to be changed too. Seems like I don't have to do that for now so there is no problem, I wanted to post this to see if there was a more practical solution to this but it seems like there isn't. In short, just make new variables and override methods, if theres other scripts that use the old variables, override the methods in those other scripts too.
Answer by JVene · Nov 02, 2018 at 10:15 PM
@Torqus Your question evokes the issues of class design, beyond that of the solution you employed. Where what you have works, let it work, but for future exploration of your summary inquiry (to see if there are more practical solutions) I submit these points as a means of discovering object design. I base these points on the assumption that since MMAchievementDisplayItem is a MonoBehaviour derivative, you created it and are thus in control of that code, as well as (more obviously), you "own" SSAchievementDisplayItem.
What you have are two ways of expressing a common (as in base level) concept. The SSAchievementDisplayItem is merely (it appears) a different way of handling the controls for "Title" and "Description". There are paradigms for handling this.
To begin, this requires that you adjust your perspective in thinking that MMAchievementDisplayItem should remain untouched (that is actually the source of your problem). It has become, now, three classes, but one of those classes has not emerged in the design yet. The third (missing) class is a base. It would handle all that MMAchievementDisplayItem now does, but perhaps without the members Title and Description. Those two are what changes in your two required implementations, and there's a conflict (and waste) you've already noticed if the proposed (missing) base owns the (more primitive) Title and Description.
So, if a base existed (maybe AchivementDisplayItemBase) which treated Title and Description as abstract ideas (in this case member variables), you'd have two classes, MMAchievementDisplayItem and SSAchievementDisplayItem which implement either required specific implementation. Now, there's no conflict. The base has neither Text or TextMeshProUGUI, it deals with the notions of the controls as abstract, thus requiring override for either implementation. Not really much different from what you post in commentary as your present solution, just cleaner.
Various languages have more advanced ways of handling this. In C++ we'd use templates, and C# has the roughly analogous "generic" means of making the TYPES of Text and Description parameters to the class. In this way one could instantiate an AcheivementDisplayItem generic class as EITHER types (Text or TextMeshProUGUI). The trick, though, is that the interface for those two types may differ, which requires specialization (or partial specialization) of the generic implementations. C# is known to be weak on this subject, but there are means that may suit your situation (Google provides, C# partial specialization). The point is that a generic class which takes the type as a parameter would be a way of writing ONE class that does either Text or TextMeshProUGUI as required, and that's even cleaner.
Never seen an answer explaining something as formal as an exploration of the $$anonymous$$d, but program$$anonymous$$g kinda comes close to it tho. Yeah this would be the better way of handling this situation. I didn't want to modify the $$anonymous$$$$anonymous$$ script because I didn't make it, it came from an asset, so I made the SS to replace it. This experience made me learn how this entire class-subclass thing works more in depth. If a third script edited the $$anonymous$$$$anonymous$$ original variable, it wouldn't matter if I'm using the SS script, the third script wouldn't work because im not using those variables anymore, so I would start a chain of changing scripts that would be 1 $$anonymous$$ute or hours of work, but I guess that's to be expected.