Иногда я вижу код С#:
Создается экземпляр, который затем вызывает конструктор, который не совпадает с конструктором типа.
Например:
Person somebody = new Member();
Какие возможные случаи могут возникнуть, и почему это желательно?
(Я думал, что это связано с вызовом конструктора базового класса, но я не мог получить это для компиляции)
Член наследования от Person или Person - это слабо названный интерфейс и Member реализует его:
Подробнее о наследовании: http://msdn.microsoft.com/en-gb/library/ms173149(v=vs.80).aspx http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)
Дополнительные сведения о интерфейсах: http://msdn.microsoft.com/en-us/library/ms173156.aspx http://en.wikipedia.org/wiki/Protocol_(object-oriented_programming)
Вы можете определить следующее с помощью наследования:
public class Person
{
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
public class Adult : Person
{
public string Workplace { get; set; }
}
public class Child : Person
{
public List<string> Toys { get; set; }
}
А затем, если вы создадите экземпляр Adult (Adult a = new Adult();
), у вас будет доступ к свойствам Name, DateOfBirth и Workplace. Аналогично с ребенком у вас будет свойство Toys.
Кроме того, вы можете сохранить список лиц, который содержит как взрослых, так и детей:
List<Person> people = new List<Person>();
people.Add(new Adult() { Name = "Adult", DateOfBirth = DateTime.Now, Workplace = "Microsoft" });
people.Add(new Child() { Name = "Child", DateOfBirth = DateTime.Now, Toys = new List<string> { "Car", "Train" } });
и затем вы можете пройти через каждую распечатку имени и даты рождения:
foreach(Person p in people)
{
Console.WriteLine(p.Name + ", " + p.DateOfBirth.ToString("dd/MMM/yy"));
if(p is Child)
{
Console.WriteLine(p.Name + " has the following toys: " + string.Join(", ", ((Child)p).Toys));
}
else if(p is Adult)
{
Console.WriteLine(p.Name + " works at " + ((Adult)p).Workplace;
}
}
Интерфейсы в основном определяют контракт (т. IPerson
Объект, который реализует IPerson
, предоставит реализации для своих методов). Это похоже на сетевую карту: существует стандарт того, как они разговаривают с сетью, но как они работают внутри, зависит от производителя, если они обеспечивают ожидаемое поведение. Интерфейсы не могут иметь в них никакой логики или хранить какие-либо данные, они просто рекламируют то, что обеспечивает реализация этого интерфейса.
public interface IPerson
{
string Name { get; set; }
DateTime DateOfBirth { get; set; }
}
public class Adult : IPerson
{
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public string Workplace { get; set; }
}
public class Child : IPerson
{
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public List<string> Toys { get; set; }
}
Существуют также абстрактные классы, которые обеспечивают некоторые функциональные возможности интерфейсов, но могут реализовывать некоторую логику. Единственное, что следует отметить во всем этом, это то, что класс может быть получен только из (т.е. наследуется) от одного класса, хотя этот класс может наследовать от другого класса. Однако вы можете реализовать несколько интерфейсов.
Это действительно, если Person
является базовым классом Member
Аналогично это также справедливо:
Object o = new Member();
Ваш вопрос не является вопросом о конструкторах. Это все о неявных преобразованиях. В вашем заявлении:
Person somebody = new Member();
правая часть оператора =
явно имеет Member
типа (время компиляции). Однако переменная у somebody
есть (время компиляции) Person
. Это законно, только если существует неявное преобразование из Member
в Person
. Тогда код действительно похож на Person somebody = (Person)(new Member());
кроме того, что "литье" невидимо.
Теперь самым обычным неявным преобразованием является ссылочное преобразование из class
в его (прямой или косвенный) базовый класс или в интерфейс, который он реализует.
Существует несколько иное неявное преобразование, преобразование бокса из struct
или enum
в его базовый класс или интерфейс.
Существуют также пользовательские неявные преобразования, которые являются своего рода методами (написанными с implicit operator
).
Есть более неявные преобразования, например, из значения типа V
в версию Nullable<>
, обычно записываемую как V?
, Но было бы странно, если бы Person
было просто using
псевдоним для Member?
, поэтому этот пример не реалистичен в вашем примере. Другой, который редко упоминается в этом примере, - это "расширение" преобразования, например, от int
до long
.
Прочтите спецификацию языка С#, чтобы узнать больше о том, какие преобразования существуют.
Member
класса, вероятно, выглядит следующим образом...
public class Member : Person {}
Где Member
происходит от Person
.
object o = new String();
или, более интуитивно,Animal fido = new Dog();