Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 在以下情况下,接口或抽象类或两者都更好吗?_Oop - Fatal编程技术网

Oop 在以下情况下,接口或抽象类或两者都更好吗?

Oop 在以下情况下,接口或抽象类或两者都更好吗?,oop,Oop,假设我有一个程序可以提取航空公司的数据。每个航空公司的数据都使用不同的系统,我需要从中提取数据(xml)。由于每个系统的不同,基本上xml是不同的,可能还有一些特性,我决定为每个航空公司系统实现一个接口。但我发现,尽管各航空公司在许多方面有所不同,但也有许多相似之处,因此,如果我首先采用接口方式,我可能必须这样做: public interface IAirlineSystem { public void PullData(); } 现在,对于每个航空公司系统(我正在编造这些名称),我

假设我有一个程序可以提取航空公司的数据。每个航空公司的数据都使用不同的系统,我需要从中提取数据(xml)。由于每个系统的不同,基本上xml是不同的,可能还有一些特性,我决定为每个航空公司系统实现一个接口。但我发现,尽管各航空公司在许多方面有所不同,但也有许多相似之处,因此,如果我首先采用接口方式,我可能必须这样做:

public interface IAirlineSystem {
    public void PullData();
}
现在,对于每个航空公司系统(我正在编造这些名称),我可能会这样做:

public class Oberon : IAirlineSystem {
    string Name {get;set;}
    int Code {get;set;}
    public void Initialize()
    {
        //initialize code here
    }
    public void PullData()
    {
       //code here
    }
}
public interface IAirlineSystem {
    public void PullData();
    public void ValidateData();
}

public abstract class BaseAirlineSystem : IAirlineSystem {
    string Name {get;set;}
    int Code {get;set;}

    public void Initialize()
    {
        // common initialize code here
    }        

    public virtual void ValidateData()
    {
       //empty, override when necessary
    }
}
以上只是一个航空公司系统,但假设我有更多(如+10),另一个可能是:

public class AirSys: IAirlineSystem {
    string Name {get;set;}
    int Code {get;set;}
    public void Initialize()
    {
        //initialize code here
    }
    public void PullData()
    {
       //code here
    }
}
在上述代码中:

名称和代码属性对于每个航空公司系统都是唯一的。Initialize为每个实现包含完全相同的代码,PullData对每个系统都是唯一的。由于类中存在重复项,在这里我可以使用抽象类来保存Initialize方法的代码。我听说,实际上混合接口和抽象类是一种很好的做法,使用我的airline系统示例,这方面的示例是什么


另一件事是,假设我在接口中有另一个名为ValidateData的方法,但不是所有的航空公司系统都需要调用它,但是如果我把它放在接口中,如果不需要,我需要实现一个空方法。有没有什么方法可以避免这样做。这是使用抽象类的另一个原因,可能与虚拟方法一起使用,以便可以根据需要重写它。如果我将ValidateData作为一个抽象方法,它仍然需要实现,对吗?

您的解释似乎指向使用抽象类。您可以有一个抽象类,该类将具有Initialize方法的实现,并且不需要在Oberon和AirSys子类中重复它。PullData可以是一个抽象方法,然后在单独的子类中实现。是的,只有需要ValidateData方法的类才会实现它

例如:

public abstract class AirlineSystemBase
{
    string Name { get; set; }
    int Code { get; set; }

    public void Initialize()
    {
        //code goes here
    }

    public abstract void PullData();

}

public class Oberon : AirlineSystemBase
{
    public override void PullData()
    {
        //code goes here
    }
}

public class AirSys : AirlineSystemBase
{
    /// <summary>
    ///     that is if say only AirSys class had a need for this ValidateData() method
    /// </summary>
    public void ValidateData()
    {
        //code goes here
    }

    public override void PullData()
    {
        //code goes here
    }

}
公共抽象类AirlineSystemBase
{
字符串名称{get;set;}
int代码{get;set;}
公共无效初始化()
{
//代码在这里
}
公共摘要void PullData();
}
公共级Oberon:航空线路系统基础
{
公共覆盖void PullData()
{
//代码在这里
}
}
公共级AirSys:AirlineSystemBase
{
/// 
///也就是说,假设只有AirSys类需要这个ValidateData()方法
/// 
公共void ValidateData()
{
//代码在这里
}
公共覆盖void PullData()
{
//代码在这里
}
}
或者,如果要同时使用接口和抽象类:

public interface IAirlineSystem
{
    void PullData();
    void ValidateData();
}

public abstract class AirlineSystemBase : IAirlineSystem
{
    string Name { get; set; }
    int Code { get; set; }

    public void Initialize()
    {
        //code goes here
    }

    public abstract void PullData();

    public virtual void ValidateData() 
    { 
        //code goes here
    }

}

public class Oberon : AirlineSystemBase
{
    public override void PullData()
    {
        //code goes here
    }
}

public class AirSys : AirlineSystemBase
{
    /// <summary>
    ///     that is if say only AirSys class had a need for this ValidateData() method
    /// </summary>
    public override void ValidateData()
    {
        //code goes here
    }

    public override void PullData()
    {
        //code goes here
    }

}
公共接口IAirlineSystem
{
void PullData();
void ValidateData();
}
公共抽象类AirlineSystemBase:IAirlineSystem
{
字符串名称{get;set;}
int代码{get;set;}
公共无效初始化()
{
//代码在这里
}
公共摘要void PullData();
公共虚拟void ValidateData()
{ 
//代码在这里
}
}
公共级Oberon:航空线路系统基础
{
公共覆盖void PullData()
{
//代码在这里
}
}
公共级AirSys:AirlineSystemBase
{
/// 
///也就是说,假设只有AirSys类需要这个ValidateData()方法
/// 
公共覆盖void ValidateData()
{
//代码在这里
}
公共覆盖void PullData()
{
//代码在这里
}
}

例如,我将实现如下内容:

public class Oberon : IAirlineSystem {
    string Name {get;set;}
    int Code {get;set;}
    public void Initialize()
    {
        //initialize code here
    }
    public void PullData()
    {
       //code here
    }
}
public interface IAirlineSystem {
    public void PullData();
    public void ValidateData();
}

public abstract class BaseAirlineSystem : IAirlineSystem {
    string Name {get;set;}
    int Code {get;set;}

    public void Initialize()
    {
        // common initialize code here
    }        

    public virtual void ValidateData()
    {
       //empty, override when necessary
    }
}
以及一个示例实现:

public class AirSys: BaseAirlineSystem{
    public void PullData()
    {
        //code here
    }
 }

如果您不介意,您能解释一下为什么要使用接口和抽象类吗?您能在基类中更改ValidateData的方法签名吗?我以为你得保持原样。我注意到在您的抽象基类中,您将签名更改为public virtual void,而不是接口中的public void。当我创建一个新的AirSys对象时,是否最好将其实例化为AirSys AirSys=new AirSys()或baseairslinesystem AirSys=new AirSys(),或者这是否重要?实际上您可能不需要该接口,如果您想让您的系统只与接口耦合,那么它是有用的。例如,需要与航空公司系统一起工作的类只能引用接口,而不需要担心它们是如何实现的。如果以后添加一个没有任何通用代码的新系统,这可能会很有用?在这种情况下,接口方法已经是虚拟的,因此没有签名更改。关于实例化:它只取决于您使用它的上下文。