[英]How do I define the signature of a function that must be implemented by instances of a class?
說我有一類Book
:
public class Book{
public string Title {get; set;}
}
我希望每本書都有一個Read
函數,該函數返回一個字符串並接受頁碼-但是每本書的內部結構都不同(我知道例子很差)。 如何定義必須由此類實例實現的功能的簽名?
像這樣:
public class Book{ // need to make this abstract?
public string Title {get; set;}
public abstract string Read(int pageNum);
}
// I want to define instances that define their own behavior...
public static Book It => new Book(){ // can't create instance of abstract...
Title = "It",
Read... // what do I do here?
}
我主要關心的是:
Tenant
。 Tenants
是在內存中定義的,並且具有許多靜態屬性,例如domain
, name
, adminEmail
等。這些是租戶特定的屬性...但是現在我正在嘗試實現租戶特定的行為 ,例如GetBooks
或FilterUsers
。 我想使實現盡可能地簡單。 現在,我的代碼中始終散布着“如果使用TenantA,請執行此操作,如果使用TenantB,請執行此操作...”。 我試圖將所有特定於租戶的邏輯和詳細信息集中在一個地方- Tenant
類的實例。 GetCoverPhoto
。 在論壇B的主頁上,您可以通過閱讀博客主頁來獲取GetCoverPhoto
。 目前,我說“如果論壇A,請執行此操作,否則,如果論壇B,請執行此操作”。 這是我想在Tenant對象上而不是在代碼中定義的特定於租戶的行為的類型。 我的核心邏輯中不需要任何特定於租戶的代碼。 C#語言中是否有一個簡單的功能/模式可以實現這一目標?
NineBerry所說的非常正確。
還有另一種方法可以實現您想要的。 如果要動態地將read方法實現注入Book中。 這可以看作是策略模式 。 並且可以像許多語言一樣作為接口來完成,但是以C#的最簡單形式可以由委托來完成。 例:
public class Book{
Func<int, string> readFunc;
public Book(Func<int, string> readFunc)
{
this.readFunc = readFunc;
}
public string Title {get; set;}
public string Read(int pageNum) { return readFunc(pageNum); }
}
然后將其用作:
public static Book It => new Book(){
Title = "It",
Read = (pageNum) => ... // Do actual reading in delegate
}
編輯:隨着需求的更多細節(但仍然不是一切都是顯而易見的),我會做這樣的事情:
public class Tenant
{
// core things go here
public Extensions Extensions { get; }
}
public class Extensions : IEnumerable<IExtension>
{
private IList<IExtension> list = new List<IExtension();
private Tenant { get; set; }
public Extensions(Tenant tenant)
{
Tenant = tenant;
}
public void Add(IExtension extension)
{
extension.Tenant = Tenant;
list.Add(extension);
}
}
public interface IExtension
{
Tenant { get; set; }
// shared interface of extensions if any can be abstracted
}
public interface ICoverPhotoExtension : IExtension
{
Photo GetCoverPhoto();
}
public class FileCoverPhotoExtension : ICoverPhotoExtension
{
public Tenant { get; set; }
Photo GetCoverPhoto() { } // gets photo from file
}
public class BlogCoverPhotoExtension : ICoverPhotoExtension
{
public Tenant { get; set; }
Photo GetCoverPhoto() { } // gets photo from blog
}
用法:
Tenant tenant; // initialized somehow
var coverPhotoExtension = tenant.Extensions.FirstOrDefault<ICoverPhotoExtension>();
Photo photo = coverPhotoExtension?.GetCoverPhoto();
public Interface IBook{
string Title {get; set;}
func<int,string> ReadPage
}
在繼承中使用包容性。 在上面的接口示例中,每本書中都有一個實現IBook的函數,該函數將為該頁面返回一個字符串。
public class MyBook : IBook{
public Title : {get;set;} = "MyBook";
public func<int,string> ReadPage =(pagenumber)=>{
return GetText(pagenumber);
}
public string GetText(int pageNumber){
//read the page text by number here.
}
}
我將使GetText成為與此類似的擴展方法,因此每本書都不需要實現GetText本身。
public static class XBook{
public static string GetText(this IBook book, int pageNumber){
///do the work here and returng string
}
}
要使用擴展方法概念:
using XBook;
public class MyBook : IBook{
public Title : {get;set;} = "MyBook";
public func<int,string> ReadPage =(pagenumber)=>{
return this.GetText(pagenumber);
}
}
有更多方法可以執行此操作...現在,嘗試一下。
一個類的不同實例無法以不同方式實現功能。 而是,您繼承一個新類,在其中實現單獨的行為。
public abstract class Book
{
public string Title {get; set;}
public abstract string Read(int pageNum);
}
public class ITBook : Book
{
public override string Read(int pageNum)
{
// Code here
}
}
然后使用這樣的類:
public static Book It => new ITBook()
{
Title = "It",
}
您可以在Book類中使用委托類型的屬性在Book類的不同實例中使用不同的函數,但是這些函數將無法訪問它們將使用的實例的其他屬性和方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.