我不明白基类的继承



我对继承的理解非常基本。

我想创建一个基类,它实现IDisposable,然后让其他具有功能的类继承自该基类,以便它们共享基类型。

它将允许我将每个对象放入一个列表中,以便我可以在想要清理时一次性处理所有内容。 问题是,C#中的类只能继承一次,否则只能使用接口。

现在,像Thread这样的类如何继承我的基类,而我基本上不必重新编写Thread类?

这听起来可能很愚蠢,但简而言之:我想让已经存在的类继承我选择的基类,而不会丢失其功能。(因此,项目中使用的所有类都有一个共同的基础,可以总结为一个对象类型,例如List)

这可能吗?

如果您的目标是简单地存储可以释放的对象列表,那么您需要一个List<IDisposable>。直接或间接实现该接口的任何类都可以存储在其中。

var disposables = new List<IDisposable>();
disposables.Add(new MyClass1());
disposables.Add(new SomeClass());
disposables.Add(new AnotherClass());
disposables.ForEach(d => d.Dispose());

这是否是一个有价值的模式,我不相信!

您给出的接口IDisposable的示例。在 C# 中,类可以实现多个接口。

另一方面,在 C# 中,类可能只从一个类继承。

话虽如此,从类继承并不总是好主意,因为它非常有限。相反,我建议作曲:维基

例如,我会建议类似组合设计模式的东西(这是一个小的变化,因为复合没有对象的集合,而只有一个对象):

public interface IFoo
{
void DoFooStuff();
}
public class Foo : IFoo
{
public void DoFooStuff() {...};
}
public class ShouldImplementFoo : IFoo
{
// Composition, you need to initialize it some time
private Foo _foo;

public void DoFooStuff() { _foo.DoFooStuff(); }
}

编辑

在重新思考你的问题之后,你似乎想把一些对象集(不同类的)放在一个列表中,这样你就可以对列表中的每个对象执行一些定义的操作

最简单的是:使用定义的操作定义接口:

public interface IMyIntf
{
void MyDesiredAction();
}

现在,让所有类实现它。现在你可能会想"好吧,现在我需要在任何地方实现这种方法......" - 没有那样的事情!只需使用适配器设计模式,例如,具有类:

public class MyConcreteClass
{
public void ActionIWishToExecuteOnThisObject() 
{ ... }
}

您只需将其修改为:

public class MyConcreteClass : IMyIntf
{
public void ActionIWishToExecuteOnThisObject() 
{ ... }
// implement interface
public void MyDesiredAction()
{
ActionIWishToExecuteOnThisObject();
}
}

现在,您可以使用一些聚合,例如List<IMyIntf>,将所有您感兴趣的对象放在那里并执行以下操作:

foreach(var item in myList)
item.MyDesiredAction();

一个类可以继承自一个祖先类(否则 Object,所有类的根)。

它还可以实现一些接口(或没有)。

类可以将非实现成员作为抽象成员,因此该类是抽象的。

成员也可以是虚拟的,以实现多态性(抽象成员是)。

一旦实现,类中就可以有一个东西,即使不是抽象的,也可以实例化,并且对所有子级也可用,除了隐藏在子类中的私有子项。

无需重复,这是OOP的强大功能之一。

这样做,使用抽象,封装,继承和多态性,在研究现实世界和我们工作的领域之后,我们可以设计这个现实世界的投影,我们脑海中的视图,概念具有数据(字段和属性)和操作(方法),分类在工件(对象)和关系,组合,聚合,接口,组件,控件等事物中。 等等。

因此,我们可以分解处理以不重复,例如:

  • 有一个Animal班和CatDog子班,
  • 我们把SizeColor方面放在动物身上,
  • 以及为所有动物实施的EatWalk方法,
  • 和一个抽象的未实现DoSound.

因此:

  • 在具体的类中CatDog我们不再次实现这些东西,
  • 除了DoSound每个真实的动物性别都是特别的。

关于接口,它们是虚拟合约。

例如,乍一看,我们可以拥有没有任何共同点的动物和建筑物(我们不会回到原子和光子),但我们希望能够管理猫和狗等物体的实例,以及房屋和博物馆拍照。

为了实现这一点,我们定义了一个接口IPhotoTaking并在定义以前的类时,我们添加它们实现此接口。

代码示例:

public interface IPhotoTaking
{
Image TakePhoto();
}
public abstract class Animal : IPhotoTaking
{
public int Size { get; set; }
public Color Color { get; set; }
public void Eat() { ... }
public void Walk() { ... }
public abstract void DoSOund();
public Image TakePhoto();
}
public class Cat : Animal // no need to repeat IPhotoTaking
{
public override void DoSound() { ... }
}
public class Dog : Animal
{
public override void DoSound() { ... }
}
public abstract class Building :IPhotoTaking
{
public Image TakePhoto();
}
public class House : Building
{
}
public class Museum : Building
{
}

现在有了这个列表,我们可以像这样使用多态性:

var animals = new List<Animal>();
foreach ( var animal in animals )
animal.DoSound();

同样没有多态性,并且由于 C# 不支持真正的多态性,但此处的菱形运算符尚未应用于List<>,因此我们可以像这样使用接口:

var items = new List<IPhotoTaking>();
foreach ( var item in items )
item.TakePhoto();

备注:如果每种类型的拍照可能不同,我们可以将其设置为虚拟,以专门用于每种类型的实现。

OOP 基本原则

什么是 C# 中的抽象?

如何在公共、私有和受保护的访问修饰符之间进行选择?

关联、组成和聚合

什么是多态性?

接口和类有什么区别?

关于 C# 中缺少真正的泛型多态性和缺少菱形运算符

最新更新