помогите с интерфейсами и абстрактными классами - PullRequest
1 голос
/ 02 сентября 2010

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

Я хотел написать несколько классов, которые бы занимались разбором xml. У меня есть разные типы пользователей, которые имеют разные требования к синтаксическому анализу.

Моя логика заключалась в следующем.

Все парсеры имеют общую функцию "разбора" и должны иметь хотя бы эту функцию, поэтому я создал интерфейс с этой функцией, определенной с именем IParse;

Я начинаю с 2 пользовательских типов, пользовательского типа A и пользовательского типа B. Пользовательский тип A & B имеет некоторые основные функции, но пользовательский тип B имеет несколько больше функций, чем A, поэтому я поместил функции для анализа того, что они разделяют, абстрактный класс, который будет расширяться, называется "ParseBase".

Так что теперь у меня есть

// Interface

    public interface IParser
     {
      function parse(xml:XML):void;
     }




// Base Class

public class ParseBase()

{
  public function getbasicdata():void{}

public function getmorebasicdata():void{}

}





//User type A

public class userTypeA extends ParseBase implement IParse

{
    public function parse(xml:XML):void
{
       getbasicdata()

       getmorebasicdata()

}


}

//user type B

public class userTypeB extends ParseBase implement IParse

{
    public function parse(xml:XML):void
{
       getbasicdata()

       getmorebasicdata()

}

   public function extraFunctionForB():void
{

}

  public function anotherExtraFunctionForB():void
{

}


}

Проблема, с которой я столкнулся сейчас, заставляет меня поверить, что я делаю что-то не так, заключается в следующем.

Допустим, я хочу добавить еще одну функцию UserTypeB. Я иду и пишу новую публичную функцию в этом классе. Затем в моей реализации я использую переключатель, чтобы проверить, какой тип пользователя создать.

Var userParser:IParser

if(a)

{
userParser= new userTypeA(); 
}else if(b)

{
userParser= new userTypeB();
}

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

Что я делаю не так?

Ответы [ 3 ]

2 голосов
/ 02 сентября 2010

Вы объявляете новую функцию только в userTypeB, а не в IParser. Таким образом, он не виден через интерфейс IParser. Поскольку userParser объявлен как IParser, вы не можете напрямую получить доступ к функциям userTypeB через него - вам нужно либо уменьшить его до userTypeB, либо добавить новую функцию к IParser, чтобы достичь .

Конечно, добавление функции к IParser имеет смысл, только если эта функция имеет смысл для всех анализаторов, а не только для userTypeB. Это вопрос дизайна, на который IMO нельзя ответить разумно, не зная больше о вашем приложении. Тем не менее, одна вещь, которую вы можете сделать, - это объединить IParser и BaseParser - ИМО, вам не нужны оба. Вы можете просто определить открытый интерфейс и некоторую реализацию по умолчанию в одном абстрактном классе.

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

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

Как сказал Питер Торок (+1), IParser объявляет только одну функцию parse(xml). Когда вы создаете переменную userParser типа IParser, вам будет разрешено вызывать только метод parse (). Чтобы вызвать функцию, определенную в подтипе, вам необходимо явно привести ее к этому подтипу.

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

Вы также можете иметь отдельный абстрактный тип BaseParser, который реализует интерфейс IParser.

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

Чтобы получить доступ к функциям для определенного подтипа (например, UserTypeB), вам нужна переменная этого типа (требует явного приведения).

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

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