-3

我读了很多关于抽象类和接口的文章,但每次我无法解释面试我不知道为什么请帮助我更好地理解这两个主题。

我对抽象类的理解是:- 抽象类是那些你想在项目中使用一些常见功能的类。就像有 2 类 1)“合同雇员” 2)永久雇员

所以在两个类中都有相同的字段,比如名字、姓氏、员工 ID、工资、总小时数

因此,根据您的合同和永久雇员,这里的工资计算是不同的,但其余的东西是相同的,所以这里需要抽象类来实现相同的功能。

接口: - 接口类似于合约,其中合约中的所有方法都应在继承类中实现。它是强制性的。

困惑:但在抽象类中也说如果你在抽象类中声明一些抽象方法,它也必须在继承类中实现?

请解释一下,以便我可以更好地理解两者

提前致谢

4

5 回答 5

3

接口只是一个合同。它定义了一个公共 API,通过它可以使用任何实现类型。一种类型可以实现多个接口。此外,接口不仅可以由类实现,也可以由结构实现。这支持 OOP 的多态性方面。它们不能包含字段或任何类型的可执行代码。

抽象类,它们都比接口更多和更少。也可以定义公共 API,但它们的主要目的是为任何派生类型提供基本功能。它们可以包含成熟的方法和属性、字段。很多时候,他们将其功能的某些方面的实际实现委托给他们的继承者。另一个区别是:

  • 任何类都可以从单个抽象(或具体)类派生
  • 只有类可以从抽象(或任何)类型派生,而不是结构

因此,接口是用于合同定义的,为了使用它们,必须实现它们。抽象类用于基本功能共享,它们派生自.

于 2013-10-27T12:54:22.020 回答
0
  1. 当您需要在相似实体之间共享一些实现细节时,抽象类很有用。
  2. 接口只声明使用对象的契约。

两种方法都可以用于多态性。

于 2013-10-27T12:46:28.843 回答
0

抽象类和接口之间的主要区别是,在抽象类中,您可以实现一些逻辑,但在接口中,您只能定义合同,而在接口中没有实现。一个所有方法都是抽象的抽象类,就相当于接口。

于 2013-10-27T12:52:57.497 回答
0

它们具有相似的特征。对我来说,在两者之间进行选择实际上是关于“有/做”和“是”之间的区别。

OO 编程的目标之一是表示现实世界中的真实对象。如果您使用继承(即抽象类),您是在说基类是您正在建模的对象的基本类型。所以一个Employee类通常继承自某种类,从接口派生比从接口派生Person更自然。EmployeePersonIPerson

另一方面,如果您想在类中实现某种行为,例如序列化,您可能希望将其表示为接口。序列化是您的类提供的一项功能,尽管它不是您的类试图表示的真实世界对象类的固有部分。这是通常被称为“横切关注点”的典型示例。

这就是为什么你可能会看到这样的声明

public class Employee : Person, ISerializable { ... }

而不是看到基类和接口以相反的方式表达。它还非常适合您可以使用多个接口的事实:在 CLR 的世界中,您的类只能有一个基本基类,但它可以表达任意数量的不同行为。

于 2013-10-27T12:51:06.060 回答
0

它们当然是相似的,并且可以通过使用两者来完成许多事情。

考虑以下课程:

public abstract class PersonBase
    {
        public string Name { get; set; }
        public DateTime BirthDate { get; set; }

        public PersonBase(string name, DateTime bd)
        {
            this.Name = name;
            this.BirthDate = bd;
        }

        public int CalculateAge()
        {
            return DateTime.Now.Year - BirthDate.Year;
        }

        public abstract string HealthRecord { get; set; }

        public abstract string DisplayData();
    }

    public class TeenagerPerson : PersonBase
    {
        public PersonBase BestFriendForever { get; set; }
        public override string HealthRecord { get; set; }
        public TeenagerPerson(string name, DateTime bd)
            : base(name, bd)
        {
        }

        public override string DisplayData()
        {
            return string.Format("Name:{0}  Age:{1}  Health record:{2}  BFF:{3}", Name, CalculateAge(), HealthRecord, BestFriendForever.Name);
        }
    }

    public class AdultPerson : PersonBase
    {
        public override string HealthRecord { get; set; }
        public AdultPerson(string name, DateTime bd)
            : base(name, bd)
        {
        }

        public override string DisplayData()
        {
            return string.Format("Name:{0}  Age:{1}  Health record:{2}", Name, CalculateAge(), HealthRecord);
        }
    }

该示例使用抽象基类来提供一些通用属性,同时允许派生类声明自己的属性。该解决方案强制派生类实现 DisplayData() 方法,该方法将类的内容显示给外部世界 - 当然是他们喜欢的。

测试代码:

var teenager = new TeenagerPerson("Joanne", new DateTime(2000, 11, 05));
teenager.BestFriendForever = new TeenagerPerson("Julia", new DateTime(2000, 10, 05));
Console.WriteLine(teenager.DisplayData());

var adult = new AdultPerson("Mike", new DateTime(1960, 01, 03));
adult.HealthRecord = "2003 - Heart Bypass";
Console.WriteLine(adult.DisplayData());

给出以下输出:

姓名:Joanne 年龄:13 健康记录:BFF:Julia

姓名:迈克 年龄:53 健康记录:2003 - 心脏搭桥

使用抽象类的选项是无限的,我当然认为它们与接口一样通用。抽象类的缺点当然是,由于 C# 没有多重继承,因此您的一次继承已经与抽象类一起使用。

PS:只是注意到我的年龄计算很糟糕,使用时间跨度可能会更好。:)

于 2013-10-27T13:06:42.257 回答