ой концепция запроса - PullRequest
       0

ой концепция запроса

6 голосов
/ 16 сентября 2010

У меня есть вопрос, связанный с концепцией OOPS.

У меня есть базовый класс

public class BaseClass
{
   public int i = 10;
   public int x = 30;
   public string str = "Hello";
   public virtual string Hello()
   {
     return "Hello of base class called";
   }
}

У меня есть детский класс

public class ChildClass : BaseClass
{
    public int i = 20;
    public int z = 90;
    public override string Hello()
    {
       return "Hello of child class called";
     }
}

Теперь я увидел, что приведенный ниже код работает нормально

BaseClass baseObject = new ChildClass();

и когда я набираю baseObject. , тогда я вижу только элементы BaseClass.

Первый вопрос: может ли кто-нибудь посоветовать мне ситуацию, в которой разработчик должен сделать это BaseClass baseObject = new ChildClass();?

Второй вопрос: если мой BaseClass объект имеет ссылку на мой дочерний объект класса, то почему мои дочерние переменные-члены не доступны через этот baseObject?

Ответы [ 6 ]

7 голосов
/ 16 сентября 2010

Чтобы ответить на ваш первый вопрос.

Разработчики делают это, чтобы обеспечить абстракцию того фактического объекта, на который они ссылаются, что обеспечивает гибкость и «слабую связь» с кодом, который его использует.

Например (общий сценарий - который я часто использую), у вас может быть 10 дочерних классов, которые расширяют базовый класс. Что если вы хотите, чтобы метод возвращал каждый тип дочернего класса? Ну, без этого типа декларации вам понадобится 10 методов. Но если вы указали тип возвращаемого значения «BaseClass», вы можете вернуть все 10 типов дочерних классов из одного метода. Этот метод тесно связан с пользователем интерфейсов.

1009 * например *

public BaseClass GetDynamicChildClass()
{
     if (someCondition) return ChildClass();
     else if (someOtherCondition) return SomeOtherChildClass();
}

Чтобы ответить на ваш второй вопрос.

Вы не можете видеть дочерние свойства, потому что вы сказали, что «baseObject» имеет тип «BaseClass» - компилятор типизировал объект этому. Чтобы получить доступ к дочерним свойствам, вам нужно привести его как дочерний тип:

BaseClass b = new ChildClass();
int x = b.z; // error.
int x = ((ChildClass)b).z; // works - this is a cast, throws exception in bad conversion
ChildClass c = b as ChildClass; // also works, different type of cast, returns null in bad conversion
int x2 = c.z; 

Этот тип концепции (полиморфизм) является фундаментальным для объектно-ориентированного программирования. Посмотрите на этот превосходный вопрос StackOverflow: Постарайтесь описать полиморфизм как можно проще

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

Надеюсь, это поможет.

1 голос
/ 16 сентября 2010

Ответ на ваш первый вопрос: этот тип реализации часто встречается, когда мы используем абстрактный фабричный шаблон для i, приведу простой пример, который создает семейство Ford Car ..

public class AbstractFactoryExample
{
    public AbstractFactoryExample()
    {
        string type = "";
        CarFactory facotry=null;
        if (type == "FORD")
        {
            facotry = new FordCarFactory();
        }
        ICar MyFamilyCar = facotry.CreateFamilyCar();
        ICar MyCityCar = facotry.CreateCityCar();
    }
}
public interface ICar
{

}
public abstract class CarFactory
{
    public  abstract ICar CreateFamilyCar();
    public  abstract ICar CreateCityCar();

}
public class FordCarFactory : CarFactory
{
    public  override ICar  CreateFamilyCar()
    {
        return new FordFamilyCar();
    }
    public override ICar CreateCityCar()
    {
        return new FordCityCar();
    }
}
public class FordFamilyCar : ICar
{

}
public class FordCityCar : ICar
{

}

дляВаш второй вопрос:

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

((ChildClass) baseObject) 

canрешить проблему

прошу прощения за мой плохой английский

1 голос
/ 16 сентября 2010

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

public class Report
{
    public virtual string ContentType
    {
        get { return "application/octet-stream"; }
    }

    public virtual byte[] Build()
    {
        return new byte[0];
    }

    public static Report Create(ReportType type)
    {
        switch (type)
        {
            case ReportType.Pdf:
                return new PdfReport();
            case ReportType.Html:
                return new HtmlReport();
            case ReportType.Doc:
                return new DocReport();
            case ReportType.Xls:
                return new XlsReport();
            default:
                return new DefaultReport();
        }
    }
}

Тогда со стороны клиента мы должны сделать только это:

ReportType type = GetReportTypeFromFormPost();
Report report = Report.Create(type);
// ...
Response.Write(report.Build());
1 голос
/ 16 сентября 2010

Когда вы делаете

BaseClass baseObject= new ChildClass();

Статическим объявленным типом объекта является тип "BaseClass".

Следовательно, вы можете видеть только объекты типа "BaseClass".

Если вы уверены, что объект имеет тип ChildClass, вы можете типизировать baseObject для «ChildClass», а затем использовать члены ChildClass

((ChildClass) baseObject). - должен помочь intellisense дать вам членов дочернего класса.

Использование BaseClass baseObject= new ChildClass(); является основой для полиморфизма RunTime . Он очень часто используется, если вам нужно вызвать переопределенную дочернюю логику, но интерфейс этого интерфейса базового класса

РЕДАКТИРОВАТЬ: Пример сценария, где вы будете использовать его Класс User имеет производные классы с именами Employee и 3rdPartyUser

Класс User имеет виртуальный метод GetRoleInformation, который используется для получения информации о роли пользователя из Active Directory компании.

Однако для стороннего пользователя, поскольку информация не существует в AD, логика получения информации о роли включает в себя вызов веб-службы для извлечения данных. В этом случае GetRoleInformation переопределяется в классе 3rdPartyUser

Теперь, в программе, на странице входа в систему, после аутентификации я либо получаю объект Employee, либо 3rdPartyUser. Я передаю этот объект методу с подписью RoleCollection GetRole( User loggedInUser)

Внутри этого метода, без необходимости определять тип пользователя, я просто вызываю loggedInUser.GetRoleInformation и в зависимости от того, является ли он Employee / 3rdPartyUser, будет вызван соответствующий базовый / переопределенный метод, и данные роли будут получены из любого из них. AD / Web Service.

Короче говоря:

Преимущество

BaseClass baseObject= new ChildClass();

OVER

ChildClass baseObject= new ChildClass();

в сценариях, когда вы не уверены в точном типе дочернего объекта, который будет назначен переменной baseObject, например: в этом случае Employee / 3rdPartyUser Например:

  BaseClass baseObject= GetLoggedInUser();

где сигнатура этого метода User GetLoggedInUser(string userid)

В противном случае, в примере, подобном вашему, где объект ВСЕГДА имеет тип "ChildClass", я считаю, что это не дает никаких преимуществ.

1 голос
/ 16 сентября 2010
  1. Если вы хотите, чтобы объекты с индивидуальным поведением имели набор общих функций. Например, вы хотите поместить объекты разных типов в список.

  2. Базовым типом по-прежнему является ChildClass, но в настоящее время вы работаете с типом BaseClass. Вот почему вы видите только членов для BaseClass. Однако все еще возможно преобразовать экземпляр BaseClass в экземпляр ChildClass с помощью операции приведения или ключевого слова as.

0 голосов
/ 16 сентября 2010

На самом деле это имеет больше смысла для вас, когда вы используете Factory Pattern (http://gsraj.tripod.com/design/creational/factory/factory.html) для создания экземпляра объекта. Это будет абстрагировать детали конкретной реализации для другого класса.

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