- Home /
Hiding an inherited variable : "The same field name is serialized multiple names in the class or it's parent class.
Hello,
My situation is the following : I have a general "WorldObject" class, with a "player" member that references the owner of the object. But I have three "Player" classes : a general one and two derived ones (made for different factions in the game, each type of player has specific methods and variables). Now what I would like to do (which may not be possible, from what I'm seeing so far) is to "change" the type of the "player" variable depending on the faction. That is, I want my "player" field to be of type "HumanPlayer" when used in a "HumanUnit" (which is another class inheriting from WorldObject) and of type "OrcPlayer" if used in an "OrcUnit". This way when I call "player.MethodSpecificToHumanPlayer())" it works and I don't have to cast every single time because by default I have access to a "HumanPlayer" and not a simple "Player".
I thought the whole "hiding" thing was made for this but apparently it only works with methods or properties. At the moment my "player" field is protected and I get that weird error in the title, which I don't really understand and searching for the others that have had the same error yielded no result.
Of course there are easy ways around that, the simplest being to create another variable named "hPlayer" of type "HumanPlayer" and then use both. That's probably what I'll end up doing anyway, but for future reference I'd like to know if what I am trying to do is at least possible or not.
Thanks in advance. Also sorry for asking something that's probably close to programmation-blasphemy. :p
Edit : since it seems I'm getting misunderstood I'll add some pseudo-code of the problem.
class A {
protected Player player;
}
class B : A {
protected HumanPlayer player;
private void Foo()
{
player.AMethodThatExistsInHumanPlayerButNotInPlayer();
}
}
Answer by YoungDevelops · Dec 01, 2017 at 03:13 AM
This is so many years late, but if anyone needs this in the future, it may be useful. I had the same issue, but I found that it means that a private variable is in the parent class that is in the child class as well. The solution is to set the repeated variables in the parent class to protected rather than private, then remove the variables from the child class.
Answer by fafase · Nov 15, 2013 at 06:45 PM
Ok I think you are after virtual and override.
TopClass{
public virtual void MyMethod(){}
}
SubClass:TopClass{
public override void MyMethod(){}
}
OtherSub:TopClass{
public override void MyMethod(){}
}
Now in your class:
TopClass objRef;
void Start(){
objRef.MyMethod();
}
Believe it or not but if you pass an object of the sub type, even though your reference is of top class the compiler will look into MyMethod and find it as virtual. So it will look down the object on case that object would have any sub class implementing that virtual method and it will call the sub class if there. This is opposed to non virtual method that if you implement the same method down the hierarchy, it will hide the top one and the compiler will suggest you to use new if intended. This would result in the method from the level the reference points to.
No I'm sorry but that's not the problem I'm talking about. I understand overriding methods but I'm asking how to hide/override VARIABLES. Let's use a quick code example because I suppose I wasn't clear in my original formulation :
Class A
{
protected int number;
}
Class B : A
{
protected float number; //Basically I want to call "number" as a float for this class with the same name
}
Edit : example might be a bit inacurrate because I don't think "float" inherits from int. In my case though, I'm actually "replacing" the variable's type by a subtype. Wanted to precise in case it changes anything.
It seems you want to use the same name for a different variable and the answer is that it is not possible, to my knowledge. It is not a question of type (and yes float does not inherits from int) but more a question of variable management. How can the compiler figure out which one you are meaning when simply using:
number = 2;
You have to come up with a different logic for your class.
Well that's where that shiny "new" keyword comes into play ! Basically when I declare "protected float number", Unity tells me that it "hides the parent class declaration", and that I should use "new" if that hiding is intended. Except that in the end, whether I use "new" or not in my declaration, it doesn't work.
Welp, guess I'll just create another variable and will remember this for later.
Answer by TehWardy · May 11, 2014 at 10:34 AM
Correct me if im wrong here but this is actually a fundamental flaw in your design.
Lets take unity out of the problem here and just look at c# as a language. If i override a variable I cannot change it's type in this manner because that would give a variable a different meaning and behaviour.
You could do this however ...
Class A {}
Class B : A
{
protected int number;
}
Class C : A
{
protected float number;
}
This way you can access number as the right type given that you have an object of the right type ...
var p = A, B, or C type
// property number not available
var baseType = ((A)p)
// property number is of type int
var bType = ((B)p);
// property number is of type float
var cType = ((C)p);
but given that you have B / C types you can now no longer cast between them as they are considered to be fundamentally different.
Answer by Dray · Dec 01, 2017 at 08:16 AM
Hiding methods and variables is not made for changing the return type, if you override a function you'll have to use the same parameters, return type and name or it will be an independent function. Now for the player variable, I wouldn't override it at all, it's redundant. 'HumanPlayer' is a Player in that case so why not just keep that as it is and add a function that casts the type to your Human- or OrcPlayer.
Or to make it even a bit cleaner you could implement a generic abstract 'Unit' class with a dynamic Type like this:
// T is your variable type. The where part is optional but I recommend using it here
public abstract class Unit<T> where T : Player
{
protected T player;
}
// player type here will be a HumanPlayer
public class HumanPlayerUnit : Unit<HumanPlayer>
{
public HumanPlayer GetPlayer() {
return player;
}
}
// player type here will be a OrcPlayer
public class OrcPlayerUnit : Unit<OrcPlayer>
{
public OrcPlayer GetPlayer() {
return player;
}
public void DoSomething() {
player.OnlyOrcPlayerMethod(); // works because the player is an OrcPlayer allready
}
}
edit: actually, let's turn this into an answer
Your answer
Follow this Question
Related Questions
An OS design issue: File types associated with their appropriate programs 1 Answer
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Derived Class Fields 3 Answers
Inherited member variables not set to base value c# 1 Answer