Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
7
Question by Jessy · Sep 10, 2010 at 12:54 AM · classclassessubclassing

Override a serialized variable from a parent class?

What I've got now, is, in the base class:

[HideInInspector] [SerializeField] protected Button button;

...and in the derived class:

[HideInInspector] [SerializeField] RecalibrateButton _button;
_button = button as RecalibrateButton;

I'd rather do

[HideInInspector] [SerializeField] new RecalibrateButton button;
button = base.button as RecalibrateButton;

...but while that doesn't generate an error when I save the script, this error comes up shortly thereafter in the Editor:

Same name multiple times included:::Base(MonoBehaviour) button

Is there some way I can use the variable name "button" to override what the base class's "button" is?

Edit: UnityAnswers proves only abysmal ability to respond to answers, so here's what I'm doing now, in the derived class:

public override void InitializeAtRuntime () {
    base.InitializeAtRuntime();
    RecalibrateButton button = base.button as RecalibrateButton;
    button.ReleaseInsideRange += OnReleaseInsideRange;
    button.ReleaseOutsideRange += OnReleaseOutsideRange;
}
Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image jashan · Sep 12, 2010 at 07:04 PM 0
Share

With your new code (InitializeAtRuntime()), unless you already make sure that button is assigned (i.e. not null) and of type "RecalibrateButton", you should probably have button.ReleaseInsideRange enclosed in an "if (button != null) { ... }", otherwise, you might run into trouble at some point in time.

3 Replies

· Add your reply
  • Sort: 
avatar image
4
Best Answer

Answer by jashan · Sep 10, 2010 at 05:04 AM

As SpikeX said - you can simply assign objects of a subclass to variables of the parent class. But obviously, there's a problem with that because you can't directly access the members that the subclass defined. So, if for example your Button has AButtonMethod() and RecalibrateButton has ARecalibrateButtonMethod(), the only way to access the latter is by doing a typecast:

((RecalibrateButton)button).ARecalibrateButtonMethod();

That's not exactly convenient, but it works. However, if RecalibrateButton overrides a method, e.g. if it has it's own definition of AButtonMethod(), the oo-runtime will automatically execute the version of RecalibrateButton when you call it. So, you might consider not creating ARecalibrateButtonMethod() when you could also override AButtonMethod(). But if that doesn't work in your specific design, you'll have to fallback to the typecast approach. One thing that I do frequently in such cases is adding a property that handles this for me (just a matter of convenience and cosmectics):

public RecalibrateButton RecalibrateButton {
    get { return (RecalibrateButton) button; }
}

That way, you can conveniently access "button" as if it was a RecalibrateButton.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Jessy · Sep 10, 2010 at 10:16 PM 0
Share

I only need to access "button" in the initialization stage. As I said in a response to SpikeX, I'm not happy about this, and can't believe the language doesn't provide a method for this kind of thing, but it will do. Also, is there some reason you prefer an explicit cast ins$$anonymous$$d of as? In my research, I've heard that "as" was a superior approach.

avatar image qJake · Sep 11, 2010 at 01:47 AM 1
Share

The only difference between (type) and as type is that "as" doesn't fail on a cast exception, it will ins$$anonymous$$d assign the value of "null" to the variable. Using "as" is safer if you check for null, basically, and if you don't like try/catching your exceptions. ;)

avatar image jashan · Sep 11, 2010 at 12:29 PM 3
Share

Actually, if you're not sure that the object is of the type you expect, you can easily do: if (button is RecalibrateButton) { ((RecalibrateButton)button).ARecalibrateButton$$anonymous$$ethod(); } In general, I think the prefix-casting is preferable because when you get an exception, you get an exception that tells you exactly what's going on. While when you get a NullReferenceException with "as-casting", either the object was null, or it was of the wrong type which makes debugging more difficult (even worse when the exception occurs later). The advantage of "as-casting" however, is that it's much faster.

avatar image
1

Answer by qJake · Sep 10, 2010 at 02:31 AM

No. That's the point of deriving from classes, the derived class inherits everything from its parent classes (everything that's public and protected, anyway). What you can do, though, is something like this, inside the constructor or elsewhere:

button = new RecalibrateButton();

since the "RecalibrateButton" is of type "Button", you can instantiate it, and the "button" becomes a "RecalibrateButton", even though it was defined as a "Button". So you don't need to redefine "button" at all (in fact, don't!), instead, just create an instance of the child class inside of it.

Polymorphism - What fun :)

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Jessy · Sep 10, 2010 at 10:47 PM 0
Share

It is not "the point". Otherwise there would be no overriding functions. It's pitiful that you can't do this with variables, the way you can with methods and even properties. Also, the constructor-based approach won't work, as this is a specific instance of RecalibrateButton that I've got set up and serialized in the Editor.

avatar image qJake · Sep 11, 2010 at 01:50 AM 0
Share

Did you read this page? It explains polymorphism in C#: (be sure to click the "C#" header on the code samples if not already) http://msdn.microsoft.com/en-us/library/ms173152(VS.80).aspx -- I'm not 100% sure what you're trying to do, or what you're mad about, but that page might shed some light on what you can and cannot do with C#/.NET.

avatar image Jessy · Sep 11, 2010 at 06:46 AM 0
Share

"Fields cannot be virtual; only methods, properties, events and indexers can be virtual." "Virtual methods and properties allow you to plan ahead for future expansion." Well, in my case, Virtual fields would do the same thing. It's a stupid limitation. There may be some important technical reason for doing things this way, but it doesn't mean that it's good for making code.

You can get an idea of what I'm doing in the edit to the question. RecalibrateButton sends two events I need to utilize (for RecalibrateButtonSounds), but Button doesn't need to send them.

avatar image Jessy · Sep 11, 2010 at 06:56 AM 0
Share

Several types of button classes derive from ButtonSounds, which has a Button for its variable "button", and all of them are just fine having button be stored as a Button, despite the fact that all of them are actually derived from Button, like PauseButton, EndButton, etc, and never Button itself. That's because the classes derived from ButtonSounds use either the virtual methods from ButtonSounds, or overridden versions of them. I only need "button" serialized so the game can start faster, as I only set up event listening and then never use the variable again. In this case, I need a R...Button

avatar image
1

Answer by Herman-Tulleken · Sep 10, 2010 at 11:26 AM

Your code is legal C#, and in my game I can get it to work if the class is not a MonoBehaviour. (Although I have not tested it with SerializeField). This makes it look like the reflection used by MonoBehviour to build inspectors, etc., might be the reason it is flagged.

The other solutions by other posters will work and are simple enough to implement, but you might also consider a refactoring which involves moving the field to a non-MonoBehaviour class. (This of course depends on the rest of your design; it might also be a terrible idea).

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Jessy · Sep 10, 2010 at 10:08 PM 0
Share

Everything being a $$anonymous$$onoBehaviour is necessary. The scripts are attached to specific Game Objects and deal with the attached Audio Sources.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

No one has followed this question yet.

Related Questions

Importing data from classes? 2 Answers

adding classes to arrays 2 Answers

Instantiate inside class function returns NullReference 1 Answer

Alternative way to have a class to store data 2 Answers

Is Instance Of 3 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges