简体   繁体   中英

Access abstract class members from childs inherits

I have an abstract class called Flight and its implement a interface called IFlight and it has a virtual method, another three classes that inherit from it, the only diffrence between those three classes is the implemantation of this method. Another thing that I want to do is implement a method that accepts as an argument an object of type IFlight (could be one of those three classes) and from them i want to access the members of the abstract class (Flight). Which way there is to implement such thing ?

Flight:

class AbsFlight: IFlight
{ 
    public int ID { get; set; }

    public string Start_Point { get; set; }

    public virtual float Calculate_Price(float Base_Price)
    {
        return Base_Price;
    } 
}

One of the classes (The other two looks similar except the method "Calculate_Price"):

class Charter: AbsFlight
{
    public override float Calculate_Price(float Base_Price)
    {
        return base.Calculate_Price(Base_Price) * 3;
    }
}

Main:

private static void Some_Method(IFlight flight)
{
    Console.WriteLine(flight.Calculate_Price(2)); //OK
    Console.WriteLine(flight.ID); //Error
}

static void Main(string[] args)
{
    List<IFlight> flights = new List<IFlight>();

    flights.Add(new Regular());
    flights.Add(new Charter());
    flights.Add(new LowCost());

    Main_SomeMethod(flights[0]);
}

Your method should accept the type that has the properties it needs, in this case the AbsFlight class.

private static void Some_Method(AbsFlight flight)
{
    Console.WriteLine(flight.Calculate_Price(2)); 
    Console.WriteLine(flight.ID); //OK
}

But let's says the method must accept any IFlight . In this case, it can't be sure it received an AbsFlight; it has to check. After the check you can just cast.

private static void Some_Method(IFlight flight)
{
    Console.WriteLine(flight.Calculate_Price(2)); 
    if (flight is AbsFlight)
    {
        Console.WriteLine(((AbsFlight)flight).ID); //OK
    }
}

With c#7 there is an additional construct you can use, if you think it is clearer:

private static void Some_Method(IFlight flight)
{
    Console.WriteLine(flight.Calculate_Price(2)); 
    switch (flight)
    {
        case AbsFlight absFlight:
            Console.WriteLine(absFlight.ID); //OK
            break;
    }
}

It seems to be that you are doing something wrong that this is your requirement.

When you use an interface and pass it as an argument you want it to be common to all the objects that implement it.

Anyway, if you do want to do it. You might do something like:

if (flight is Flight)
{
    Flight yourFlight = (Flight)flight;
    // Here you can use anything you need from Flight, e.g: yourFlight.ID
}

Your current solution, in combination with some of the suggestions, will be a case of a mounted riding rider . You don't need an interface and a base class and testing for type.

You can solve your problem the way you're trying, with a base class and an interface. But it's overkill, and you have to kind of duplicate some stuff in the interface and the base class.

You can solve your problem with a simple base class and three derived classes where only Calculate_Price gets overridden. Put the common items in the base class. This is a very simple solution, easy to figure out, especially if C# and OOP is new to you.

You can also solve your problem with an interface and three classes, not derived. This has the disadvantage that you have to implement the interface in three classes. As Peter Csala points out, C# 8 has some language features that can help minimize this work, possibly making this just as simple as using only a base class and no interface. I am not too familiar with those features, so I can't judge whether it makes sense.

Then there is another option entirely. This touches on what zaitsman hinted at - that this is possibly an XY problem. Why do you want to distinguish between Regular, Charter and LowCost using classes derived from Flight/AbsFlight? Is it possible to just have an attribute that tells what price profile is used? Are there other fields and properties of a Flight that has nothing to do with the price, and yet also distinguishes flights? Perhaps just use one class.

About testing for class type. This is what we call code smell. Generally, if you test for class types a lot, then you defy the purpose of using classes and/or interfaces in the first place.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM