是否可以在抽象类和接口中使用相同的字段名称?
本文关键字:字段 抽象类 接口 是否 | 更新日期: 2023-09-27 18:14:09
我正在创建一些类,我需要征求您的意见。让我们想象一下这样的情况:
我们有一个抽象类A
:
abstract class A {
public int Id {get; set;}
}
我们有三个类实现它B
, C
和D
:
class B : A {
public List<string> Comments {get; set;}
public List<string> Categories {get; set;}
}
class C : A {
public List<string> Categories {get; set;}
}
class D : A {
public List<string> Comments {get; set;}
}
正如你所看到的,一些属性是常见的,我想把它们提取到另一个类/接口。所以理论上我可以创建以下接口:
interface IWithCategories {
List<string> Categories {get; set;}
}
interface IWithComments {
List<string> Comments {get; set;}
}
让B
, C
和D
实现他们需要的。问题是,当我使用IWithCategories
时,我还需要A
的属性。
这个问题有什么好的解决方案?
我的想法如下:
我从
A
中提取接口,称为IA
。A
当然会实现IA
。interface IA {int Id{获取;设置;}}
抽象类A: IA {公共int Id{获取;设置;}}
IWithComments
和IWithCategories
将扩展IA
:interface IWithCategories: IA {列表类别{get;设置;}}
interface IWithComments: IA {列表注释{get;设置;}}
然后
B
,C
和D
可以实现它们:类B: A, IWithCategories, IWithComments {公共列表评论{get;设置;}公共列表类别{获取;设置;}}
类C: A, IWithCategories {公共列表类别{获取;设置;}}
类D: A, {公共列表评论{get;设置;}}
我知道在这一点上,B
, C
和D
类不需要扩展抽象类A
, 但是它有一些实现,将在所有类之间共享,如equals, string和一些受保护的方法。
这个方法可以接受吗?
编辑:
我正在使用Xamarin编写一个iOS应用程序,我开始只有类A
, B
, C
和D
。在某种程度上,我遇到了一种情况,我正在创建一个ViewController,应该用于所有具有Comments
字段的类,这是当我提出提取接口的想法。但是,我还需要调用一个web服务,我需要在A
上声明Id
,现在我正在考虑如何处理这个问题。
好吧,为什么接口需要setter呢?我假设它们不需要。接口是否需要暴露List<string>
而不是IList<string>
,我假设不需要。然后你有这些接口定义。
public interface IWithCategories {
IList<string> Categories { get; }
}
public interface IWithComments {
IList<string> Comments { get; }
}
现在,如果这些接口是public
,你不能阻止他们被谁选择这样做。如果您将它们保存为internal
,则只有您的程序集可以使用它们。
如果你想让abstract class A
实现这些接口,你可以这样定义它,
public abstract class A : IWithCategories, IWithComments
{
abstract public int Id { get; }
abstract public IList<string> Categories { get; }
abstract public IList<string> Comments { get; }
}
A
的继承者如何实现IWithCategories
、IWithComments
和Id
属性,不能在接口定义的契约中定义。
但是,您可以设想这样的实现,
public class B : A
{
private readonly int id;
private readonly List<string> categories;
private readonly List<string> comments;
public B(
int id,
IEnumerable<string> categories
IEnumerable<string> comments)
{
this.id = id;
this.categories = (categories ?? Enumerable.Empty<string>()).ToList();
this.comments = (comments ?? Enumerable.Empty<string>()).ToList();
}
public override int Id
{
get { return this.id; }
}
public override IList<string> Categories
{
get { return this.categories; }
}
public override IList<string> Comments
{
get { return this.comments; }
}
}
关于品类1:
如果您有多个IA
接口的实现,并且抽象类是唯一的,那么这是很好的。那么就没有理由创建额外的抽象层了。特别是当实现抽象类基部分依赖于该方法时。
关于第2点:
IWithCategories : IA
和IWithComments : IA
你应该采用单一责任原则。还要注意,命名可以反映更多的。net约定ICategorizable
和ICommentable
。那些话不正确,但表达了意思。
还要记住接口应该提供一些功能。如Jodreli所写的那样,在里面设置setter将打开你的API。
关于第3点:
在这一点上真的很难建议,因为你的例子真的很抽象和模糊。最终的实现可能因B、C和D类的原因而异。这里的提示是,您应该促进组合而不是继承,并确保类B、C和D确实是A概念的好例子。