Question:
I have the following code in C#:
namespace ConsoleApplication4
{
public class BaseClass
{
public BaseClass()
{
System.Console.WriteLine("BaseClass::BaseClass();");
}
}
public class DerivedClass : BaseClass
{
public int num;
public DerivedClass(int x)
{
num = x;
System.Console.WriteLine("DerivedClass::DerivedClass(int x);");
}
}
class Program
{
static void Main()
{
BaseClass A = new DerivedClass(20);
//B.num = 20; Erro
//Mas se converter para DerivedClass e mostrar resultado do 'num':
DerivedClass B = (DerivedClass)A;
System.Console.WriteLine(B.num); //Ele mostra o resultado que modificou no construtor! Ué? Por que isso pode?
/* Resultado:
* BaseClass::BaseClass();
* DerivedClass::DerivedClass(int x);
* 20
*/
System.Console.ReadKey();
}
}
}
The comments in the code are self-explanatory.
Answer:
The problem is that your reference A
, of type BaseClass
, can hold a reference to any object of BaseClass
, not just DerivedClass
. Thus, there is no way for the compiler to know in advance what the real type of the object pointed to by A
, and thus to know that it has the type DerivedClass
(and therefore the field num
).
(ok, in this case, it would even be possible if the compiler was "smart", but not in others)
For example, what if you had:
static void teste(BaseClass A)
{
System.Console.WriteLine(A.num);
}
static void Main()
{
teste(new DerivedClass(20)); // tem o campo num
teste(new BaseClass()); // NÃO TEM o campo num! O que acontece agora?
}
To avoid such problems, the compiler only lets you access the fields it's sure are there, hence the error when trying to do A.num
.
Formally speaking, A
static type is BaseClass
, and A
dynamic type at that time of execution is DerivedClass
. Since C# is a statically typed language, what counts when accessing an object's field is its static type. If it were a dynamically typed language (like JavaScript, Python, Ruby, etc) then this command would work – but on the other hand, it would cause a runtime error if the object contained in A
did not have the field num
.