也许这是一个愚蠢的问题。但是,我不明白我错过了什么。
给出以下类定义
public abstract class AbstractBaseClass
{
public abstract void Create(AnotherAbstractClass param1);
}
定义了AnotherAbstractClass
public abstract class AnotherAbstractClass
{
}
具体实施
public class AnotherConcreteImplementation : AnotherAbstractClass
{
}
我希望能够覆盖Create
方法以使用具体类型:
public class ConcreteImplementation : AbstractBaseClass
{
public override void Create(AnotherConcreteImplementation param1) <-- There is no suitable method for override
{
// param1 is an instance of the concrete implementation
}
public override void Create(AnotherAbstractClass param1) <-- this is working but I'll have to cast on each implementation
{
// param1 is an instance of the abstract class and needs a cast
}
}
这根本不可能,还是有某些方法我不知道?也许使用泛型?
编辑#1 (添加了更多上下文)
我正在尝试实现/强制执行在具体实现中只有一个参数有效。
可以把它想象成一个数据库层。 Create
方法将在数据库中创建一个新条目。由于每个表都有不同的值,create-parameter也有。
内部气味(在我看来)可以通过AnotherAbstractClass
的任何具体实现来调用。
public class AddressTable : AbstractBaseClass
{
public override void Create(AnotherAbstractClass param1)
{
// cast to concrete instance
var casted = (ConcreteAddressCreate)param1;
}
}
public class CityTable : AbstractBaseClass
{
public override void Create(AnotherAbstractClass param1)
{
// cast to concrete instance
var casted = (ConcreteCityCreate)param1;
}
}
拥有AddressTable
的实例我可以致电
addressIntance.Create(new ConcreteAddressCreate()); // would be okay
另一方面,我可以称之为
addressIntance.Create(new ConcreteCityCreate()); // would be okay but will fail at runtime with InvalidCastException
编辑#2 (其他信息)
稍后还可以使用更抽象的方法扩展AbstractBaseClass
类。
所以,对我来说,更有可能使用泛型方法而不是具体的类实现,每个方法都要实现200个通用参数。
答案 0 :(得分:2)
它违反了Liskov替换原则,所以你完全没有理由这样做。也就是说,你不能只是&#34;有&#34;这样的协方差是免费的:
AbstractBaseClass bcl = new ConcreteImplementation();
bcl.Create(new DifferentImplementationWithoutSecondAbstract());
合同AbstractBaseClass定义make Create
必须与传入的AbstractBaseClass
的任何实现一起使用 - 如果你对你可以传递的内容给出约束。违反了它定义的合同。
就像你假设的那样 - 你可以使用泛型:
// notice the recursive definition, we require the generic parameter
// to be a generic parameter of itself - allowing AbstractBaseClass
// to not be aware of its subclasses like in the other answers.
public abstract class AbstractBaseClass<T> where T : AbstractBaseClass<T>
{
public abstract void Create(T param1);
}
public class Concrete : AbstractBaseClass<Concrete>
{
public override void Create(Concrete param1)
{
Console.WriteLine("Hello!");
}
}
答案 1 :(得分:2)
是的,你可以使用泛型来做到这一点:
public abstract class AbstractBaseClass<T>
where T : AnotherAbstractClass
{
public abstract void Create(T param1);
}
public class ConcreteImplementation : AbstractBaseClass<AnotherConcreteImplementation>
{
public override void Create(AnotherConcreteImplementation param1)
{
}
}
答案 2 :(得分:0)
泛型确实是这样做的方式。
$.ajax({
url: resource_str,
type: "GET",
async: true,
},
success: function(data) {
var file = new Blob([data], {type: 'text/plain'});
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
var a = document.createElement("a");
a.href = fileURL;
a.download = "Testing.pdf";
document.body.appendChild(a);
a.click();
$(window).on('focus', function(e) {
$('a').remove();
});
},fails: function (data){
console.log('Error');
}
})
然后你可以这样做:
public abstract class AbstractBaseClass<TDerivedClass> where TDerivedClass : AnotherAbstractClass
{
public abstract void Create(TDerivedClass param1);
}