0

Let's say that we have 2 classes. The first one is Person

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace People
    {
        class Person
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
        }
    }

The second one is Teacher

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace People
{
    class Teacher:Person
    {
        public string Position { get; set; }
    }
}

And I want to make a teacher object using this syntax Person teacher = new Teacher(); When I make it and I try to refer to the Position property, I can't... Why does this happen? I can instead use this syntax Person teacher = new Teacher() {Position="boss" }; but even though, after that I can't refer to the teacher position using "teacher.Position".

Codor
  • 17,447
  • 9
  • 29
  • 56
peter
  • 57
  • 1
  • 3
  • 1
    The variable is of type `Person`, which has no `Position` property. Did you mean to add that property to `Person`? Related to this, look into something called the Liskov Substitution Principle. Meaningful type inheritance is more than just what keywords are used where. – David Mar 31 '17 at 12:31
  • 5
    Related: [What is polymorphism, what is it for, and how is it used?](http://stackoverflow.com/questions/1031273/what-is-polymorphism-what-is-it-for-and-how-is-it-used) – Samir Aguiar Mar 31 '17 at 12:31
  • Before asking this question you should read something about polymorphism, as @SamirAguiar proposed. – Gh61 Mar 31 '17 at 12:34
  • @Gh61 already did... – peter Mar 31 '17 at 12:36
  • @peter basically this limitation is the compiler always ensuring that you never try to access memory that you should not be able to. As you can cross reference and assign variables from multiple assemblies that do not even need to be a concrete implementation like an interface, the compiler makes sure that what ever you declare as a variable can be safely accessed. As the `Person` class doesn't have a `Position` property, the compiler will not let you access it, even if the actual object acutally has that property. – Adwaenyth Mar 31 '17 at 12:41

5 Answers5

3

You can reach it this way:

Person teacher = new Teacher() { Position="boss" };
var position = ((Teacher)teacher).Position;
teo van kot
  • 12,350
  • 10
  • 38
  • 70
2

The problem is caused by the type of the reference. In the declaration

Person teacher = new Teacher() { Position="boss" };

the right-hand side creates a new object of type Teacher and also initializes the Position property. However, the reference teacher is of type Person. While the object referred to by teacher is actually of type Teacher, the reference itself is of the more general type Person.

Informally speaking, in the above declaration you state that you want to refer teacher to a Person, regardless of whether it is of the more derived type Teacher, so the reference itself does not 'know' that it refers to the more special type Teacher and therefor does not 'know' that there is a Position property.

More technically speaking, this is necessary because at runtime it would be possible to let teacher refer to other objects deriving from Person, say Student or Wizard, which would perhaps also would not have a Position property.

Codor
  • 17,447
  • 9
  • 29
  • 56
1

Doing this:

Person teacher = new Teacher();

You create object of type Teacher but your reference type(teacher) is of type Person - it means that using this reference you can access only all members of type Person.

To access Teacher members you should either create reference of type Teacher:

Teacher teacher = new Teacher();
var position = teacher.Position;

or you should cast your reference to Teacher type:

Person teacher = new Teacher();
var position = ((Teacher)teacher).Position;
Codor
  • 17,447
  • 9
  • 29
  • 56
Roman
  • 11,966
  • 10
  • 38
  • 47
0

The reason is, the compiler simply does not know the inherited type after you assigned it to a variable explicitly declared as the base type.

The reason for that is, that while the object is still clearly an instance of Teacher the compiler can only be sure that this object is a Person at runtime, thus it will not allow you to access any properties of the Teacher class.

Declaring the variable as var will let the compiler determine the type of that variable based on what was assigned to it.

Adwaenyth
  • 2,020
  • 12
  • 24
0

read about Abstract Factory design pattern :)
That will answer your question.