什么是抽象

深入理解抽象与编程设计

大多数人对“抽象”一词的第一反应是形容词的抽象(abstract),于是总不自觉地将之与“深奥”、“模糊”、“不直观”、“不具体”等相关联,这固非大谬,然而在编程设计中,人们关注或强调的抽象更多地当是名词的抽象(abstraction)或动词的抽象(abstract,指“抽象化”)。比如著名的针对接口编程(programming to interface)原则、依赖反转(Dependency Inversion)原则,本质上都是提倡针对抽象编程,这样做的好处暂且不提,代码一定会因此变得更不直观、更难操纵、更不自然、更难理解吗?恐怕未必吧。如果说增加的抽象层(abstraction layer)(比如abstract class、interface等)有时会制造一些复杂的话(但最终目的是为了减少复杂),那么普通API的调用则是再常见不过了。相比一个API清晰的接口和明确的规范,它的冗长、复杂的实现代码虽然更加具体,但不是更难以把握和理解吗?


设计(不限于编程设计)中的抽象与口语中的抽象并不完全等同,由于其相对性和普适性,看似具体的事物也有抽象的一面,看似抽象的事物也有具体的一面。在提及抽象时,建议少通过形容词(abstract)来联想,多用名词(abstraction)或动词(抽象化)。或者更好地,根据上下文把抽象直接替换为“规范”(specification)、“约定”(convention)、“协议”(protocol)、“概念”(concept)、“语义”(semantic)、“接口”(interface)、“服务”(service)、“职责”(responsibility)之类的名词,或“忽略”、“分离”、“提炼”、“抽取”之类的动词。而抽象的对立面,用“具体”、“具象”、“明晰”、“直观”等就不如“细节”(detail)、“实现”(implementation)等来得更贴切。


模型是抽象的结晶,而抽象成功的标志之一是形成引起共识的概念。


理想的抽象是对某一概念本质特征进行精准的捕捉和描述,不要多也不要少。多则限制该抽象的适用范围,少则不能充分利用该抽象的特性。


在某些场合下,抽象没有提供足够的信息。为了挖掘必要的信息,人们不得不钻开抽象严密封装的外壳(crust),深入到它声称能够忽略的、此时却不能忽略的内部细节,由此形成了泄露。


抽象是对付复杂的有效工具。一方面,通过抽象剔除或屏蔽非本质的部分、提炼并合并本质的部分(即《冒号课堂》中提到的减法与除法),从而降低复杂性;另一方面,通过抽象对复杂分而治之,比如,宏观上水平分层(layer),垂直分区(partition),微观上分模块、分步骤,等等。

除了复杂外,软件设计的另一大敌人是变化。当具体的代码缺失了抽象的外壳,便丧失了必要的缓冲区,一旦变化来临,难免引发代码的强烈震荡。总而言之,把抽象作为设计的出发点,不仅能更合理地组织代码,而且为代码之间划分了明确的概念边界。这种边界的划分越合理、边界的规范越明晰、边界内的代码越遵循规范,系统越稳定、越易维护。


http://blog.zhenghui.org/2011/04/18/more-words-on-abstraction/

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

所以抽象(abstraction)不是vagua,而是high level;它起码要能达到实现隔离,能在更高的层次talk或者能用languange in problem domain来talk,即上文提到的concept。


### 抽象类和抽象方法的作用及使用详解 #### 抽象抽象类是指设计为被继承的类,不能被直接实例化。它通常作为其他类的基类,为派生类提供共享的属性、方法和实现逻辑。抽象类使用 `abstract` 关键字声明,可以包含抽象成员和普通成员的任意组合。抽象类的主要作用是为其派生类提供一个统一的接口和共享的实现逻辑[^2]。例如: ```csharp abstract class AbClass { public abstract void Method(); } ``` 抽象类的一个关键特性是它允许包含抽象方法,这些方法没有具体的实现,必须在派生类中实现。此外,抽象类可以包含虚方法,这些方法具有默认实现,并且可以在派生类中被重写。 #### 抽象方法 抽象方法是没有实现的方法,它只有定义和声明,没有具体实现。抽象方法使用 `abstract` 关键字声明,并且只能在抽象类中定义。抽象方法的主要作用是为其派生类提供一个统一的方法接口[^1]。例如: ```csharp abstract class Shape { public abstract double Area(); } ``` 在派生类中,必须实现所有从抽象类继承的抽象方法。例如: ```csharp class Circle : Shape { public double Radius { get; set; } public override double Area() { return Math.PI * Radius * Radius; } } ``` #### 抽象类和抽象方法的应用场景 抽象类和抽象方法主要用于以下场景: - **提供共享的实现逻辑**:抽象类可以包含普通方法和虚方法,这些方法可以提供默认的实现,避免在每个派生类中重复实现[^5]。 - **定义统一的接口**:抽象方法为派生类提供一个统一的方法接口,确保派生类实现特定的功能[^1]。 - **支持多态性**:通过虚方法和抽象方法,C# 实现了多态性,允许派生类重写基类的方法,提供不同的实现[^3]。 #### 抽象类的特点 - **不能创建实例**:抽象类不能直接实例化,只能通过派生类实例化[^4]。 - **可以包含多种成员**:抽象类可以包含抽象成员、虚成员和普通成员[^4]。 - **支持访问修饰符**:抽象类支持 `public`、`protected` 和 `internal` 等访问修饰符[^4]。 - **单继承限制**:一个类只能继承一个抽象类[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值