我最近对界面和抽象类感到有些困惑,我觉得我并没有像我想的那样完全掌握它。我想我正在使用它们不正确。我将描述我此刻正在做的事情,我遇到的问题,然后希望很清楚我做错了什么。
我想编写一些用于解析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。我去那个班级写一个新的公共函数。然后在我的实现中,我使用一个开关来检查要创建的Usertype。
Var userParser:IParser
if(a)
{
userParser= new userTypeA();
}else if(b)
{
userParser= new userTypeB();
}
如果我然后尝试访问该新功能,我在代码提示中看不到它。我看到的唯一函数名是接口中定义的函数。
我做错了什么?
答案 0 :(得分:2)
您只能在userTypeB
中声明新功能,而不能在IParser
中声明。因此,通过IParser
的界面无法看到它。由于userParser
被声明为IParser
,您无法通过它直接访问userTypeB
的函数 - 您需要将其向下转换为userTypeB
,或添加新的函数IParser
来实现这一目标。
当然,向IParser
添加函数只有在该函数对所有解析器都有意义时才有意义,而不仅仅是userTypeB
。这是一个设计问题,如果不了解您的应用程序,IMO无法合理地回答。你可以做的一件事就是联合IParser
和BaseParser
- IMO你不需要两者。您只需在单个抽象类中定义公共接口和一些默认实现。
除此之外,这与抽象类无关 - 考虑重新标记标题。顺便提一下,您显示的代码ParseBase
似乎不是抽象的。
答案 1 :(得分:0)
为了访问特定子类型的函数(例如,UserTypeB),您需要变量属于该类型(需要显式转换)。
当您只需要接口中定义的方法时,使用接口和抽象类很有用。如果你正确地构建了界面,这应该是大部分时间。
答案 2 :(得分:0)
正如Peter Torok所说(+1),IParser只宣告一个函数parse(xml)
。当您创建IParser类型的变量userParser时,您将被允许调用parse()方法。为了调用子类型中定义的函数,您必须将其显式地转换为该子类型。
在那种情况下IMO你应该重新思考你设计解析器的方式,一个例子是在你的IParser中放置一个声明(如果你在这里做了这个摘要并且在这里有共同的基本功能),它允许子类型(解析器)在解析之前和之后做一些自定义。
您还可以使用单独的BaseParser抽象类型来实现IParser接口。