Polymorphic overloading - how to make an abstract type "act" as one of its derived types for the purpose of overloaded parameters?

DoSomething(Car car);
DoSomething(Bike bike);

public class Car : Vehicle {}
public class Bike : Vehicle {}
public abstract class Vehicle {}


void run(Vehicle vehicle) {
    DoSomething(vehicle);
}

This seems like a simple problem, but I have problems. DoSomething (Vehicle vehicle) does not exist, therefore DoSomething (vehicle) gives an error even if the car is "guaranteed" like a car or a bicycle. How can I convince the compiler that a “car” is a bicycle or a car, so that DoSomething can be started?

Of course, I could have a different method line by line

DoSomething(Vehicle vehicle)
{
    if(vehicle is Car) ... etc
}

But of course, is there a cleaner approach?

EDIT / CLARITY

The motivation for placing this code in the manager class, rather than the presence of DoSomething () in the Vehicle class, is that each car should have access to different parts of the program. For instance:

DoSomething(Car car) {
    motorwayInfo.CheckMotorwayStatus();
}
DoSomething(Bike bike) {
    cycleInfo.CheckCyclePathStatus();
}

, , , Car - cycInfo, , - motorWayInfo. , DoSomething Vehicle, , :

DoSomething(CycleInfo cycleInfo, MotorwayInfo motorwayInfo)

DoSomething(InfoManager infoManager)

, , . ?

+5
5

- ? , , , () , ( ) - Vehicle.

class Vehicle
{
    public abstract void Behave();
}

class Car : Vehicle
{
    public override void Behave()
    {
        // Do something specific to a car
    }
}

class Bike : Vehicle
{
    public override void Behave()
    {
        // Do something specific to a bike
    }
}
...
void Run(Vehicle vehicle)
{
    vehicle.Behave();
}

, . Run , . , Vehicle, , . .

Run, , Vehicle. , , ..

void Run(Vehicle vehicle)
{
    vehicle.Behave();

    List<Vehicle> list = ...
    list.Add(vehicle);
}
+5

, , Double Dispatch #.

, :

public void DoSomething(Car car) {}
public void DoSomething(Bike bike) {}

public abstract class Vehicle
{
    // ...
    public abstract void CallDoSomething();
}

public class Car : Vehicle
{
    public override void CallDoSomething()
    {
        DoSomething(this);
    }
}

public class Bike : Vehicle
{
    public override void CallDoSomething()
    {
        DoSomething(this);
    }
}

, , dynamic, , , :

void run(dynamic vehicle)
{
    DoSomething(vehicle);
}

. MSDN

+2

"" ,

. , - , , - . .

, "" - , DoSomething ?

- , :

if (vehicle is Car) (vehicle as Car).CheckMotorwayStatus();
else if (vehicle is Bike) (vehicle as Bike).CheckCyclePathStatus();

, , ?

, , - .

, Car - cycInfo, , motorWayInfo.

- . :

public abstract class Vehicle
{
    public abstract void PrintRouteStatus();
}

public class MotorwayInfo
{
}

public class CycleInfo
{
}

public class Car : Vehicle
{
    // probably pass this in via a constructor.
    public MotorwayInfo _motorwayInfo = new MotorwayInfo();
    public override void PrintRouteStatus()
    {
        Console.WriteLine(_motorwayInfo);
    }
}

public class Bike : Vehicle
{
    // probably pass this in via a constructor.
    public CycleInfo _cycleInfo = new CycleInfo();
    public override void PrintRouteStatus()
    {
        Console.WriteLine(_cycleInfo);
    }
}

, .

public static void Main()
{
    var p = new Program();
    p.DoSomething(new Car());
    p.DoSomething(new Bike());
}

public void DoSomething(Vehicle v)
{
    v.PrintRouteStatus();
}
+1

, . , , , .

public abstract class Vehicle {}
public class Car : Vehicle {}
public class Bike : Vehicle {}

public void DoSomething<T>(T _vehicle) where T : Vehicle
{
    // _vehicle can be an instance of Car or Bike

    if (_vehicle is Car _car)
        motorwayInfo.CheckMotorwayStatus();

    if (_vehicle is Bike _bike)
        cycleInfo.CheckCyclePathStatus();
}

IVehicle.

0

FWIW, , "DoubleDispatchObject", - ,

1) ( , ),

2) ( ),

3) .

:

public class VehicleManager
{
  // boilerplate start
  private DoubleDispatchObject dispatch;

  public void DoSomething(Vehicle vehicle) =>
    this.EnsureThreadSafe(ref dispatch)
    .Via(nameof(DoSomething), vehicle, () => throw new NotImplementedException());
  // boilerplate end

  public void Run(Vehicle vehicle) =>
    DoSomething(vehicle);

  public void DoSomething(Car car) =>
    Console.WriteLine("Doing something with a car...");

  public void DoSomething(Bike bike) =>
    Console.WriteLine("Doing something with a bike...");
}

public abstract class Vehicle { }
public class Car : Vehicle { }
public class Bike : Vehicle { }

class MainClass {
  public static void Main (string[] args) {
    var manager = new VehicleManager();
    manager.Run(new Car());
    manager.Run(new Bike());
    Console.WriteLine("Done.");
  }
}

repl.it:

https://repl.it/@ysharp_design/SO48975551

See also this related retrieval request (for unit tests):

https://github.com/waf/MultipleDispatchBenchmarks/pull/1/files

"NTN

0
source

Source: https://habr.com/ru/post/1694113/


All Articles