在C#中使用Func <t>的多态性

时间:2015-12-21 19:48:40

标签: c# polymorphism func

上周我遇到了一个有趣的问题,我不确定我是否真正了解following code的多态性。我根据我编写的一些代码创建了这个示例。

基本设置

  • 我有一个“训练师”课程,知道如何训练动物。
  • 我使用它作为基类,并创建了一个知道如何只训练狗的子类“DogTrainer”。
  • 我使用超类作为返回类型创建了一个函数指针。
  • 然后我调用该函数获取子类“DogTrainer”的新实例。
  • 然后我调用从函数指针返回的实例的“Train”方法。
  • “训练”方法按预期调用“训练师” - “训练”方法而不是“DogTrainer” - “训练”方法

这是代码

// Does not work as expected
// Calls the Trainer Train not the DogTrainer Train
var getTrainer = new Func<Trainer>(() => new DogTrainer(new Dog()));
var funcTrainer = getTrainer();
Console.WriteLine(funcTrainer.Train());

现在,如果我使用接口作为返回类型,它确实按预期工作“IF”我在“DogTrainer”子类上直接标记了接口

// Works as expected 
var getITrainer = new Func<ITrainer>(() => new DogTrainer(new Dog()));
var funcITrainer = getITrainer();
Console.WriteLine(funcITrainer.Train());

如果我在子类上没有接口,则它不能按预期工作。 See Example

// Does not work as expected 
// Calls the Trainer Train not the Dog Trainer Train
var getITrainerWithNoInterface = new Func<ITrainer>(() => new DogTrainerWithNoInterface(new Dog()));
var funcITrainerWithNoInterface = getITrainerWithNoInterface();
Console.WriteLine(funcITrainerWithNoInterface.Train());

如果有人能让我知道我在这里缺少什么,这种行为并不是我的预期。当我在我的代码中发现这个错误时,我能够解决它,我在这里寻找的是“为什么”这种情况正在发生。

以下是DogTrainerWithNoInterface,这可能是谜题的主要部分(Trainer:ITrainer

public class DogTrainerWithNoInterface : Trainer
{
    public DogTrainerWithNoInterface(IAnimal animal)
        : base(animal)
    { }

    public new string Train()
    {
        return $"Speak Ubu, Speak : {Animal.Speak()}";
    }
}

1 个答案:

答案 0 :(得分:1)

注意:此答案纯粹是为了描述由于不符合评论而导致的“新”问题。请忽略投票,因为它没有完全回答他的问题。

来自OP链接的

示例:

function onEdit() {

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var newDate = Utilities.formatDate(new Date(), "PST", "M/d/yyyy");
  var nonMemberTracking = memberTracking();

  var currentSheet = ss.getSheetByName("Current Projects");
  var currentRange = currentSheet.getRange(currentSheet.getLastRow() + 1, 1);
  var currentColumnToWatch = 15;
  var currentActiveCell = currentSheet.getActiveCell();

  var currentRangez = currentSheet.getRange("A3:T"); 


  var parkinglotSheet = ss.getSheetByName("Parking lot");
  var parkinglotRange = parkinglotSheet.getRange(parkinglotSheet.getLastRow() + 1, 1); 
  var parkinglotColumnToWatch = 15;
  var parkinglotActiveCell = parkinglotSheet.getActiveCell();

  var completedSheet = ss.getSheetByName("Completed");
  var completedRange = completedSheet.getRange(completedSheet.getLastRow() + 1, 1); 
  var completedColumnToWatch = completedSheet.getRange("O2:O").getValue();
  var completedActiveCell = completedSheet.getActiveCell();

  var waitingSheet = ss.getSheetByName("Waiting to be assigned");
  var waitingColumnToWatch = 4;
  var waitingActiveCell = waitingSheet.getActiveCell();
  var waitingRange = waitingSheet.getRange(waitingSheet.getLastRow() + 1, 1); 

  currentRangez.sort([{ column : 4, ascending: true},{ column : 11, ascending: true}])

  if(waitingActiveCell.getColumn() == waitingColumnToWatch && waitingActiveCell.getValue() !== ""){


    currentSheet.insertRowAfter(currentSheet.getLastRow());
    waitingSheet.getRange(waitingActiveCell.getRow(), 9, 1).setValue("YES");
    waitingSheet.getRange(waitingActiveCell.getRow(), 1, 1, waitingSheet.getLastColumn()).moveTo(currentRange);
    waitingSheet.deleteRow(waitingActiveCell.getRow());
    currentSheet.sort(4);


  } else if(currentActiveCell.getColumn() == currentColumnToWatch && currentActiveCell.getValue() == "Parking lot"){

    parkinglotSheet.insertRowAfter(parkinglotSheet.getLastRow());
    currentSheet.getRange(currentActiveCell.getRow(), 1, 1, currentSheet.getLastColumn()).moveTo(parkinglotRange);
    currentSheet.deleteRow(currentActiveCell.getRow());
    parkinglotSheet.sort(4);

  } else if(currentActiveCell.getColumn() == currentColumnToWatch && currentActiveCell.getValue() == "Complete"){

    completedSheet.insertRowAfter(completedSheet.getLastRow());
    currentSheet.getRange(currentActiveCell.getRow(), 1, 1, currentSheet.getLastColumn()).moveTo(completedRange);
    currentSheet.deleteRow(currentActiveCell.getRow());
    completedSheet.sort(4);
    nonMemberTracking;

  } else if(parkinglotActiveCell.getColumn() == parkinglotColumnToWatch && parkinglotActiveCell.getValue() !== "Parking lot"){

    currentSheet.insertRowAfter(currentSheet.getLastRow());
    parkinglotSheet.getRange(parkinglotActiveCell.getRow(), 1, 1, parkinglotSheet.getLastColumn()).moveTo(currentRange);
    parkinglotSheet.deleteRow(parkinglotActiveCell.getRow());
    currentSheet.sort(4);

  }}

声明方法/属性时,请勿使用jQuery(document).on('click','.thumbnails .zoom', function(){ var photo_fullsize = jQuery(this).find('img').attr('src').replace('-76x88','-540x623'); jQuery('.woocommerce-main-image img').attr('src', photo_fullsize); }); 。在基础上创建public class DogTrainer : Trainer, ITrainer { public DogTrainer(IAnimal animal) : base(animal) { } public new string Train() { return $"Speak Ubu, Speak : {Animal.Speak()}"; } } ,然后new。你正在做的是将方法隐藏在你的基础上。

使用该特定类型(virtual)时,您只能调用override方法。对基数的任何向下转换都会调用它的方法,即使用声明为newDogTrainer的变量。

Knowing When to Use Override and New Keywords (C# Programming Guide)

相关问题