Как использовать экземпляр родительского объекта с дочерним классом - PullRequest
5 голосов
/ 02 июля 2011

Скажите, пожалуйста, как создается экземпляр родительского объекта с дочерним классом, например:

 public class A
    {
        public A()
        {
            Console.WriteLine("A");
        }
        public virtual void method()
        {
            Console.WriteLine("AM");
        }

    }
    public class B : A
    {
        public B()
        {
            Console.WriteLine("B");

        }
        public new void method()
        {
            Console.WriteLine("BM");

        }
        public void method1()
        {
            Console.WriteLine("BM1");
        }
    }

 class Program
    {
        static void Main(string[] args)
        {
            A obj = new B();// what is use of it?
            obj.method();              
            Console.Read();
        }
        private void methodP1()
        {

        }
    }

Скажите, пожалуйста, как используется Parent obj = new Child ();так как я, мы можем вызывать только открытые методы родительского класса, что возможно с помощью Parent obj = new Parent ();

возможно ли: Child obj = new Parent ()?

Ответы [ 8 ]

9 голосов
/ 02 июля 2011

скажите, пожалуйста, для чего нужен Parent obj = new Child ();как я, мы можем вызывать только открытые методы родительского класса, что возможно с помощью Parent obj = new Parent ();

Это основа для полиморфизма : представьте, что у вас естьнесколько дочерних классов, которые наследуют от вас родительский класс.Вы хотите использовать все эти дочерние классы через интерфейс / методы, определенные в родительском классе, не беспокоясь о деталях реализации в каждом дочернем классе (каждый может делать что-то свое, но с одинаковой общей семантикой).

Это возможно, потому что дочерний класс имеет отношение IS A со своим родительским классом, так как дочерний класс наследует от родительского.

6 голосов
/ 02 июля 2011

BrokenGlass ответ правильный. Однако ваш образец будет работать по-разному в зависимости от того, объявите ли вы obj как тип A или B.

В случае A obj = new B(); программа выдаст A B AM, поскольку компилятор связывается с виртуальным методом A.method, который затем наследует класс B.

В случае B obj = new B(); программа выводит A B BM, поскольку компилятор направлен на использование нового метода B.method ().

Если вместо этого B.method() было объявлено как public override void method(), то результатом всегда будет A B BM независимо от того, был ли объект объявлен как тип A или тип B.

Таким образом, ваш пример не показывает полиморфизм в классическом смысле, так как метод, вызываемый для экземпляров типа B, зависит от типа переменной, которой назначен экземпляр. Это может сделать отладку веселой и интересной.

6 голосов
/ 02 июля 2011

В вашем примере B is-a A, но A is-not-a B.

Вышесказанное полезно, когда код используетссылка на B может понимать (или должна понимать) только типы A. B является специализацией A. Представьте что-то вроде (псевдокод)

Shape s;
if (x == 1) {
  s = new Square();
}
else {
  s = new Triangle();
}
// following code knows only about Shapes
s.draw();
s.calculateArea();

Следующий код неНе нужно знать, является ли s квадратом или треугольником, просто это форма.Какая польза от этого?Если вы звоните s.draw(), форма сама определяет, как она будет выглядеть.Код, вызывающий его, не знает и не заботится.

Это ключевой момент объектно-ориентированного программирования. Просить объекты делать что-то для вас, а не определять себя, что нужно .

Обратите внимание, что ваш последний вопрос не имеет смысла интуитивно при использовании этого примера.

Форма s = новая площадь ();// штраф

против

Square s = new Shape ();// можете ли вы создать "форму" и почему тогда вы решили, что это квадрат?

2 голосов
/ 02 июля 2011

Причина, по которой вы бы использовали полиморфизм, заключается в том, что вы можете передать более конкретный объект объекту, который требует только более общего объекта. Сущность, которая получает объект, заботится только об открытом интерфейсе, а не о деталях того, как выполняются методы в этом интерфейсе. Вот простая иерархия классов:

public class Animal
{
    public virtual string GetFood()
    {
        return "Food";         
    }
}

public class Monkey : Animal
{
    public override string GetFood()
    {
        return "Bananas";
    }
}

public class Cow : Animal
{
    public override string GetFood()
    {
        return "Grass";
    }
}

А вот как вы можете использовать полиморфизм:

class Program
{
    static void Main(string[] args)
    {
        Animal[] animalArray = { new Monkey(), new Cow() };
        foreach (Animal a in animalArray) {
            WhatDoIEat(a); // Prints "Bananas", then "Grass"
        }         
    }

    static void WhatDoIEat(Animal a)
    {
        Console.WriteLine(a.GetFood());
    }
}
1 голос
/ 02 июля 2011

Нет смысла в простых примерах, подобных вашему, где область применения переменной ограничена.Но важно понимать, что в переменных .NET есть типы, которые являются статическими, известными во время компиляции, и даже если obj сохраняет ссылку на класс Child, он все равно имеет тип Parent.

И когда у вас есть метод, который требует Parent, вы можете передать ему obj (с типом Child) (и он все еще ведет себя как Child) - это пример Child ссылка по типу Parent.

Child obj = new Parent() невозможна, Parent не Child, компилятор не позволит назначить объект переменной несовместимого типа.

1 голос
/ 02 июля 2011

Если вам нужно использовать только методы родительского класса, вы можете пойти дальше и создать его экземпляр.Целью дочернего класса является добавление функциональности к родительскому классу при сохранении родительского класса.Инстанцирование родителя через ребенка без дальнейшего использования дочерних функций не имеет смысла.

0 голосов
/ 24 октября 2015

Когда вы знаете общие функции о классе, который наследуется, и когда вы не знаете точного дочернего элемента, вы можете поместить данные в родительский класс, когда бы вы ни знали о дочернем классе, вы можете присвоить ему эти значения.

0 голосов
/ 02 июля 2011

Допустим, у вас есть родительский класс с именем Animal и дочерние классы с именами Dog, Cat и Lizard. У каждого класса есть вызов метода makeSound (). Затем, когда вы говорите Animal a1 = new Dog(); и Animal a2 = new Cat(), a1.makeSound() будет лаять, а a2.makeSound() мяукает.

Технический термин для этого поведения называется полиморфизмом. Это полезно для повторного использования кода. Вам нужно только один раз написать код для приложения, в котором есть Animals makeSound (), когда они счастливы, вместо отдельного кода для каждого типа животных.

Еще одно использование полиморфизма - скрытие реализации вашего кода от других пользователей. Например, вы можете показать другим пользователям, что вы используете список, а затем у вас есть возможность реализовать список в виде LinkedList или ArrayList. Вы также можете выбрать LinkedList, а затем переключиться на ArrayList без влияния на пользователей.

Вы также не можете сказать Dog d = new Animal(), потому что Собака - это Животное, но Животное не обязательно является Собакой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...