/*ArrayList 集合类 |
* ArrayList<E> ArrayList<String> |
* ArrayList<Student> <> E是指引用数据类型 把存储的数据数据类型放在里面 |
* 基本数据类型要用对应的包装类才行首字母大写 (特殊的两个) int->Integer char->Character |
* |
* public ArrayList(); //构造方法 |
* ArrayList<Student> list =new ArrayList<Student> 基本格式 后面的<>中在 |
* 1.7版本后可以省略 |
* 集合默认10个大小 超过的时候会自动扩容 |
* public boolean add(E,e); add的返回值是boolean 类型 |
* public E remove(int index); remove |
* public E get(int index) get 获取制定元素 |
* public int size () size 获取集合的长度 |
* |
* ArrayList<String> list1=new ArrayList<String>(); |
* boolean a=list1.add("地球"); -->a=true; |
* list1.remove(5); 删除索引为5的第六个元素 |
* String c=list1.get(3); 获取第四个元素 |
* int length=list1.size(); 获取集合的长度 |
* |
* public ArrayList<Integer> getList(ArrayList<String> list2 ); |
* 定义一个公共的 返回值为集合 参数为 字符串类型集合的 方法 |
* public ArrayList<String> a=new Arraylist<>(); |
* |
* |
* 静态 static |
* static 修饰变量 这个变量:类变量 在程序运行时把变量放到变量池 然后同类中任何方法即对象 |
* 且值公用,都可以调用 |
* static 修饰方法 :类方法 静态方法 可以调用静态方法 |
* 不可以直接调用成员变量和成员方法 |
* 成员方法可以调用静态变量 和静态方法 |
* 静态方法中不可以使用this super |
* 因为静态方法要先编译,而this是指使用类中变量或方法 |
* 都还不存在,怎么使用 即static 类和方法优于对象之前加载 |
* 静态代码块 即静态方法 静态方法的调用就是直接调用静态方法名 |
* |
* 继承 : extends |
* public class zi extends fu(){ 子类可以调用父类的变量 ,如果是私有变量直接用get set |
* } 如果是非私有变量 需要加Super 在调用时,先看变量是否重名 |
* 不重名 不影响,重名默认使用子类的 |
* |
* class Fu(){ 方法重名:即重写 子类重写父类方法 返回值类型,方法名 |
* public void fuHhow(){ |
* syso("fushow"); 和参数列表都相 声明不变,重新实现 即方法体变了 |
* } |
* |
* } |
|
* class Zi extends Fu(){ 方法重写:若调用 操作子类就可以了,方法名不一样,不影响,重名直接使用 |
* 子类,若重名还要使用父类的方法,加super |
* public void ziShow(){ |
* syso("ziShow"); this.成员变量 调用本类变量 |
* } super. 父类 |
* this.成员方法() |
* super. |
* } this.() 本类无参构造 |
* super.() 父类无参 |
* public class Demo(){ 构造是不能重写的,因为重写的方法名与类名一样,而构造名必须和类名一样 |
* |
* main(){ |
* Zi z=new Zi(); 类与类之间方法的调用 先创建(new)类 |
* z.Zishow(); 然后调用 .方法名 |
* |
* 被static修饰的成员可以并且建议通过类名直接访问。虽然也可以通过对象名 |
* 访问静态成员,原因即多个对象均属 于一个类,共享使用同一个静态成员,但 |
* 是不建议,会出现警告信息。 |
* Fu.Fushow |
* } 静态代码块:类中方法外 ,加载类时只会加载一次,优于main |
* |
* } |
* |
* |
|
Arrays类 |
* public static String toString(int [] a) 静态有参构造 |
* Arrays.toString(arr) 使用方法:Array是类名, toString是静态方法 (不同类的静态方法的调用) |
* syso(Array.toString(arr)) 输出arr的字符串形式 [1,2,5] |
* |
* |
* public static void sort(int[] a) 对指定的数组进行排序 |
* Arrays.sort(arr); 无返回值 通过类名调用 |
* |
* Math类 |
* public static double abs(double a) 返回 double 值的绝对值 |
* public static double ceil(double a) :返回大于等于参数的小的整数。 |
public static double ceil(double a) :返回大于等于参数的小的整数。 |
public static double ceil(double a) :返回大于等于参数的小的整数。 |
|
* doublle a=Math.abs(21.5); 定义a 等于 21.5的绝对值 |
* |
* 抽象类 :abstract |
* public abstact class (){ } 含有抽象方法的类叫抽象类 |
* 修饰符 + abstact class(){ } 抽象类不可以实现,调用, 因为他什么都没有,就是一个壳子 |
* 需要够着方法,子类需要重写父类,需要用到父类的变量 |
* |
* public abstact void show(); 没有方法体的方法 |
* 修饰方法 abstact 返回值 方法名(){} 可以被重写,不可被调用 |
1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。 |
理解:假设 |
2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。 |
理解:子类的构造方法中,有 默认的super(),需要访问父类构造方法。 |
3. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象 类。 |
理创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。 |
解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有 意义。 |
|
* 接口 方法的集合:interface 只能放抽象方法(JDK7) ,默认方法 静态方法 (类名调用)(JDK8) 私有方法(1.9) |
* 接口也会被编译成class文件 和类差不多,但本质上不是类 他不可以创建对象,可以被接口的子类实现, |
* |
* 在接口中抽象方法的abstact 可以省略 |
* |
* 创建一个接口 |
* public interface Animal{ |
* //接口是方法的集合 |
* //抽象方法 |
* public abstact void eat();//抽象方法 |
* public void sleep();//默认方法 |
* public default void method() //静态方法 |
* public static void method1() //私有方法 |
* |
* 类实现接口 类是接口的子类 implements 接口里有方法,必须重写所有方法 |
* 类继承抽象类 类是抽象类的子类 接口不可以被创建,但是可以被子类实现 |
* 接口亦可以说是规范 创建一个接口 别的子类实现的时候都得按照规范来写 |
* |
* 创建接口 |
* public interface Person{ |
* public void work(); |
* public void play(); |
* |
} |
* |
* public class chinese inplements Person{ |
* |
* public void work(){ |
* |
* }; |
* public void play(){ |
* }; |
* |
* } |
* |
* pubic class Test{ |
* |
* } |
* |
* } |
* |
* 一个类可以继承多个接口 |
* public class 类名 implements 接口名1,接口名2。。。 |
* 若多个接口中抽象方法重名,实现类整合性全部重写(接口中 |
* 方法为抽象方法,因此重名无关紧要,重要的是重写所有接口中的抽象类) |
* |
* 一个接口可以继承多个接口 也是用extends |
* |
* 抽象方法:变量没有限制 方法有四种 |
* |
* 接口:成员变量只能是 public static final 定义一个 这种被final修饰的静态常量 接口中不能 |
* 有静态代码块和静态方法(1.7) 1.8可以放静态方法 代码块不行(因为静态代码块要用静态变量) |
* |
抽象类 编辑 讨论 |
|
抽象类往往用来表征对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同, |
但是本质上相同的具体概念的抽象。 |
通常在编程语句中用 abstract 修饰的类是抽象类。在C++中,含有纯虚拟函数的类称为抽象类, |
它不能生成对象;在java中,含有抽象方法的类称为抽象类,同样不能生成对象。 |
抽象类是不完整的,它只能用作基类。在面向对象方法中,抽象类主要用来进行类型隐藏和充当全局变量的角色。 |
目录 |
1 概念理解 |
▪ c#中的抽象类的特征 |
2 比较区别 |
▪ 与具体类比较 |
▪ 与接口比较 |
3 运用要求 |
▪ C++ |
▪ C# |
▪ Java |
4 运用实例 |
▪ C++ |
▪ C# |
▪ Java |
5 运用意义 |
概念理解 |
编辑 |
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的, |
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。 [1] |
抽象类往往用来表征对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同, |
但是本质上相同的具体概念的抽象。 [1] |
比如,在一个图形编辑软件的分析设计过程中,就会发现问题领域存在着圆、三角形这样一些具体概念, |
它们是不同的,但是它们又都属于形状这样一个概念,形状这个概念在问题领域并不是直接存在的, |
它就是一个抽象概念。而正是因为抽象的概念在问题领域没有对应的具体概念, |
所以用以表征抽象概念的抽象类是不能够实例化的。 [1] |
c#中的抽象类的特征 |
抽象类具有以下特性: |
抽象类不能实例化。 |
抽象类可以包含抽象方法和抽象访问器。 |
不能用 sealed 修饰符修饰抽象类,因为这两个修饰符的含义是相反的。 采用 sealed 修饰符的类无法继承,而 abstract 修饰符要求对类进行继承。 |
从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实际实现。 |
比较区别 |
编辑 |
与具体类比较 |
抽象类不能直接实例化,并且对抽象类使用 new 运算符会导致编译时错误。虽然一些变量和值在编译时的类型可以是抽象的, |
但是这样的变量和值必须或者为 null,或者含有对非抽象类的实例的引用(此非抽象类是从抽象类派生的)。 |
允许(但不要求)抽象类包含抽象成员。 |
抽象类不能被密封。 |
与接口比较 |
抽象类表示该类中可能已经有一些方法的具体定义,但是接口就仅仅只能定义各个方法的界面(方法名,参数列表,返回类型),并不关心具体细节。 |
接口是引用类型的,和抽象类的相似之处有三点: |
不能实例化; |
包含未实现的方法声明; |
派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他成员)。 [2] |
抽象类与接口紧密相关。然而接口又比抽象类更抽象,这主要体现在它们的差别上: |
类可以实现无限个接口,但仅能从一个抽象(或任何其他类型)类继承,从抽象类派生的类仍可实现接口,从而得出接口是用来解决多重继承问题的。 |
抽象类当中可以存在非抽象的方法,可接口不能,且它里面的方法只是一个声明必须用public来修饰没有具体实现的方法。 |
抽象类中的成员变量可以被不同的修饰符来修饰,可接口中的成员变量默认的都是静态常量(static final)。 |
抽象类是对象的抽象,然而接口是一种行为规范。 |
抽象类里面可以有非抽象方法但接口里只能有抽象方法 声明方法的存在而不去实现它的类被叫做抽像类(abstract class), |
它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。 |
不能创建abstract 类的实例。然而可以创建一个变量,其类型是一个抽像类,并让它指向具体子类的一个实例。 |
不能有抽像构造函数或抽像静态方法。Abstract 类的子类为它们父类中的所有抽像方法提供实现, |
否则它们也是抽像类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。 |
接口(interface)是抽像类的变体。在接口中,所有方法都是抽像的。多继承性可通过实现这样的接口而获得。 |
接口中的所有方法都是抽像的,没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似, |
除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。、 |
然后,它可以在实现了该接口的类的任何对像上调用接口的方法。由于有抽像类,它允许使用接口名作为引用变量的类型。 |
通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换,instanceof 运算符可以用来决定某对象的类是否实现了接口 |
运用要求 |
编辑 |
C++ |
标准c++没有abstract关键字,代之使用纯虚类实现类似的功能,详见词条“虚类”。 |
在实现接口时,常写一个抽象类,来实现接口中的某些子类所需的通用方法, |
接着在编写各个子类时,即可继承该抽象类来使用,省去在每个都要实现通用的方法的困扰。 |
C# |
抽象类应主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。 |
接口着重于CAN-DO关系类型,而抽象类则偏重于IS-A式的关系。 |
接口多定义对象的行为;抽象类多定义对象的属性。 |
如果预计会出现版本问题,可以创建“抽象类”。例如,创建了狗(Dog)、 |
鸡(Chicken)和鸭(Duck),那么应该考虑抽象出动物(Animal)来应对以后可能出现猪马牛的事情。 |
而向接口中添加新成员则会强制要求修改所有派生类,并重新编译,所以版本式的问题最好以抽象类来实现。 |
从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实现。 |
对抽象类不能使用new关键字,也不能被密封,原因是抽象类不能被实例化。 |
在抽象方法声明中不能使用 static 或 virtual 修饰符。 [3] |
Java |
abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。 |
但是,一个类却可以实现多个interface。 |
在abstract class 中可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface中, |
只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在 interface中一般不定义数据成员), |
所有的成员方法都是abstract的。 |
abstract class和interface所反映出的设计理念不同。其实abstract class表示的是"is-a"关系, |
interface表示的是"like-a"关系。 |
实现抽象类和接口的类必须实现其中的所有方法。抽象类中可以有非抽象方法。接口中则不能有实现方法。 |
接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。 |
抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋值。 |
接口中的方法默认都是 public,abstract 类型的。 [1] |
运用实例 |
编辑 |
C++ |
为了让一个类成为抽象类,至少必须有一个纯虚函数。包含至少一个纯虚函数的类视为抽象类。 |
纯虚函数形式如下: |
1 |
virtualreturntypefunction()=0; |
例如,类A有两个纯虚函数lock()、unlock()和一个虚析构函数: |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
classA |
{ |
public: |
virtualvoidlock(void)=0; |
virtualvoidunlock(void)=0; |
virtual~A(void); |
} |
将函数lock()和unlock()初始化为0使它们成为纯虚函数,没有0这个初使化器,它们仅仅是虚函数。 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
classB:publicA |
{ |
protected: |
pthread_mutex_tx; |
public: |
B(void); |
~B(void); |
virtualvoidlock(void) |
{ |
ead_mutex_lock(x); |
} |
virtualvoidunlock(void) |
{ |
ead_mutex_unlock(x); |
} |
} |
抽象类对于提供模式、蓝图和后代类遵循的原则有用, |
如果遵循了蓝图的语义,后代类的行为可能按抽象类提供者和使用者所期望的那样。 |
通过使用抽象类,C++程序员可以提供C++组件的规范,在它的构建中指导组件的实现者。 |
C# |
抽象类提供多个派生类共享基类的公共定义,它既可以提供抽象方法,也可以提供非抽象方法。 |
如果派生类没有实现所有的抽象方法,则该派生类也必须声明为抽象类。另外, |
实现抽象方法由overriding方法来实现。 [3] |
定义方法为: |
/// |
///定义抽象类 |
/// |
abstractpublicclassAnimal |
{ |
//定义静态字段 |
staticprotectedint_id; |
//定义属性 |
publicabstractstaticintId//在抽象方法声明中不能使用static或virtual修饰符 |
|
{ |
get; |
set; |
} |
//定义方法 |
publicabstractvoidEat(); |
//定义索引器 |
publicstringthis[inti] |
{ |
get;//必须声明主体,因为它未标记为abstract、extern或partial |
|
set; |
} |
/// |
///实现抽象类 |
/// |
publicclassDog:Animal |
{ |
publicstaticoverrideintId |
{ |
get{return_id;} |
set{_id=value;} |
} |
publicoverridevoidEat() |
{ |
Console.Write("DogEats.") |
} |
} |
[3] |
Java |
假设在问题领域中有一个关于Door的抽象概念,该Door具有执行两个动作open和close, |
此时可以通过abstract class或者interface来定义一个表示该抽象概念的类型,定义方式分别如下所示: |
使用abstract class方式定义Door: |
abstractclassDoor{ |
|
abstractvoidopen(); |
|
abstractvoidclose(); |
|
} |
使用interface方式定义Door: |
interfaceDoor{ |
voidopen(); |
voidclose(); |
} |
[4] |
其他具体的Door类型可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。 |
就此看来,使用abstract class和interface没有大的区别。 |
但如果需求要求Door还要具有报警的功能,就能得出差别。既然open、close和alarm属于两个不同的概念, |
根据ISP原则应该把它们分别定义在代表这两个概念的抽象类中。 |
对于问题领域的理解是:AlarmDoor在概念本质上是Door,同时它有具有报警的功能。说明它又能够完成报警概念中 |
定义的行为,所以报警概念可以通过interface方式定义。如下所示: |
abstractclassDoor{ |
abstractvoidopen(); |
abstractvoidclose(); |
} |
interfaceAlarm{ |
voidalarm(); |
} |
classAlarmDoorextendsDoorimplementsAlarm{ |
voidopen(){…} |
voidclose(){…} |
voidalarm(){…} |
} |
这种实现方式基本上能够明确的反映出对于问题领域的理解,正确的揭示设计意图。 [4] |
运用意义 |
编辑 |
在面向对象方法中,抽象类主要用来进行类型隐藏。构造出一个固定的一组行为的抽象描述, |
但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类, |
而这一组任意个可能的具体实现则表现为所有可能的派生类。模块可以操作一个抽象体。 |
由于模块依赖于一个固定的抽象体,因此它可以是不允许修改的;同时,通过从这个抽象体派生, |
也可扩展此模块的行为功能。为了能够实现面向对象设计的一个最核心的原则OCP(Open-Closed Principle), |
抽象类是其中的关键所在。 [1] |
* */ |