【黑马程序员】 java笔记——抽象类

来源:互联网 发布:windows10下安装mysql 编辑:程序博客网 时间:2024/06/05 00:29
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------

抽象类

一、面向对象(抽象类1

当多个类中出现相同功能,但是功能主体不同,这是可以进行向上抽取的。这时,只抽取功能定义,而不抽取功能主体。

抽象:看不懂。

抽象类的特点:

1、  抽象方法一定在抽象类中。

2、  抽象方法和抽象类都必须被abstract关键字修饰。

3、  抽象类不可以用new创建对象。因为调用抽象方法没意义。

4、  抽象类中的抽象方法要被使用,必须由子类复写起所有的抽象方法后,建立子类对象调用。

如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。

二、面向对象(抽象类2

抽象类和一般类没有太大的不同。

该如何描述事物,就如何描述事物,只不过,该事物出现了一些看不懂的东西。

这些不确定的部分,也是该事物的功能,需要明确出现,但是无法定义主体。

通过抽象方法来表示。

抽象类比一般类多了个抽象函数,就是在类中可以定义抽象方法。

抽象类不可以实例化。

特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。

1.抽象类

abstract 修饰的类被称为抽象类。所谓抽象类就是没有具体实例对象的类。

抽象类通常包括一个或多个抽象方法(只有方法说明,没有方法体),抽象类的子类必须完成父类定义的每一个抽象方法,除非该子类也是抽象类。

抽象类的主要用途是用来描述概念性的内容,这样可以提高开发效率,更好地统一用户“接口”。

2. 定义一个抽象类

abstract class   类名称

{

     成员变量;

     方法();              //定义一般方法

     abstract  方法();    //定义抽象方法

}

说明:抽象类中可以包含有一般方法,也可以包含有抽象方法;对于抽象方法不用完成其代码实现,而在派生的子类中实现所有抽象方法。

3. 抽象类实现的例子

如前所述你可能对抽象类的概念有点模糊,下面举一个具体实例来作说明。

假设想设计一个形状(shape)的父类CShape,由此类可派生出圆形(circle),长方形(rectangle)于三角形(triangle)等几何形状的类。则父类于子类的派生关系描绘成如下图所示。

4.需求假设

假设这些几何形状均具有“颜色”(color)这个属性,因此可以把color这个数据成员,以及赋值color的方法均设计在父类里,让它继承给各个形状的子类较为方便,如此就不用在每一个几何形状的子类里,设计相同的程序代码来处理“颜色”这个属性的问题。

另外,如果想为每一个几何形状的类设计一个area()方法,用来显示几何形状的面积,因每种几何形状的面积计算方式并不相同,所以把area()方法的处理方式设计在父类里并不恰当,但每一个由CShape父类所派生出的子类又都需要用到这一个方法,因此可以在父类里只声明area()方法,而把area()方法处理的方法留在子类里来定义,也就是说,把area()声明成抽象方法即可解决这个问题。根据上述的概念,可编写出如下的父类程序代码:

abstract class CShape     //定义抽象类{    protected String color;    //数据成员    public void setColor(String str)    {              color=str; //一般的方法,用来赋值几何形状的颜色    }    abstract void area();//抽象类内的抽象方法}class CRectangle extends CShape{         int width,height;       publicCRectangle (int w,int h)         {          width=w;          height=h;         }         public void area()         {         System.out.print(“color=“+color+”,  “);         System.out.print(“area=“+width*height);         }} Public class app10-1{    public static void main (Stringargs[]){      CRetangle rect=newCRectangle(5,10);      rect.setColor(“yellow”);              rect.area();          CCircle  cir=new CCircle(2.0)         cir.setColor(“Green”);          cir.area();      }}

抽象类

抽象方法的特征:

抽象方法需要使用abstract关键字修饰

抽象方法没有方法体

抽象方法在参数列表后面没有大括号,但有一个分号。

具有一个或多个抽象方法的类必须声明为抽象类。

抽象类的子类,有两条路可以走:

         把父类所有抽象方法都实现完成,这样子类就不用再抽象了;

         不实现,或者不实现所有抽象方法,那么对子类来说也有未完成的方法,那么子类也需要声明为抽象类。

 抽象方法不能是静态的,也不能是private的,更不能是final的。与多态冲突的东西都不行。

抽象类是否可以有构造器:

思考:构造器是用来干什么的?与new使用创建实例对象。

思考:抽象类不能创建实例对象,那么它有构造器有没有用?

子类是不是需要调用父类构造器?需要,那么也就是说抽象类可以有构造器,而构造器是给子类构造器来用的。

abstract class A{        public A(String s) {}        public abstract void fun();}abstract class B extends A{        public B()                   {                   super("hello");               }        public void fun()                   {                        System.out.println("hello");               }}

抽象类是否可以不定义抽象方法?

抽象类可以不定义抽象方法,但很少有人这么做。

一个类如果有一到多个抽象方法,那么这个类必须声明为抽象类。

abstract关键字与什么关键字冲突?

privatestaticfinal

如果你的方法中,存在以上任意一个修饰符,那么这个方法就不能是抽象方法。

在什么时候使用抽象类?

当你想调用一个方法,而这个方法的参数类型为抽象类类型!

public class Test{        public static void main(String[] args)         {               A a = new B();               abc(a);        }        // 该方法的参数类型为A类型        // A类型是抽象类        // 我们无法实例化A类型的对象        // 说明我们需要写一个A类的子类,然后实例化子类的对象,        // 最后使用子类对象来调用abc方法。        public static void abc(A a)         {         } }abstract class A{           publicabstract void fun(); }class B extends A{        public void fun()         {         }}

当我们想使用abc()方法时,因为abc()方法的参数是A类的,而且A类是抽象类,那么我们就需要创建一个A类的子类类型对象,然后用这个对象来调用abc()方法。

         1.创建A类的子类

         2.创建子类对象

         3.用这个对象来调用abc()方法

public class Test{        public static void main(String[] args)         {                   /*                   自己来写三个Waiter的子类,用每个子类的对象来调用fun()方法                  */        }        public static void fun(A a)         {                   a.service();        } }abstract class Waiter {        public abstract void fun1();        public abstract void fun2();        public void service()         {                   fun1();                   serv();                   fun2();        }        public void serv()         {                   System.out.println("服务...");        } }

抽象类

可以有实例属性、静态属性

可以有构造器

可以有实例方法、抽象方法、静态方法

就是什么都可以有,就是不能有实例对象(不能创建对象)。

抽象类一般都会有抽象方法,即没有加工的地方。

 

抽象类、子类的变量和函数与父类的关系:

父类代码:

  

//父类,抽象类abstract public class A{ static{          System.out.println("A");       }     int i;     A(int i)         {           this.i = i;           System.out.println("A "+i);         } abstractpublicvoid f1(); abstractpublicvoid f2(); publicvoid f3() {     System.out.println("A f3 "+i);  }}

父类是个抽象类,可以有自己的数据成员,也可以有非abstarct的成员方法。但是不能被实例化。

子类1代码:

 

 //子类, publicclass C1 extends A  {      C1(int i)     {        super(i);        i++;        System.out.println("C1 "+i);     } publicvoid f1() {    System.out.println("C1 f1 "+i); } publicvoid f2() {    }    publicvoid f3() {    i=5;   System.out.println("C1 f3 "+i);   System.out.println("C1 f3 super "+super.i);   super.f3(); }}

         该子类C1实现了父类所有的方法,抽象和非抽象的。

子类2代码:

  // 子类  publicclassC2 extends A  {      C2(int i)     {         super(i); // 必须在第一行,且         this.i=8;         System.out.println("C2 "+this.i);            } publicvoid f1() {  } publicvoid f2() {    System.out.println("C2 f2 "+i); } }

子类C2实现了父类的抽象方法。子类在继承抽象类时,必须实现抽象类中的所有抽象方法。

   publicstaticvoid main(String[]args )         {             System.out.println("main start");          C1 c1 = new C1(0);          C2 c2 = new C2(0);          System.out.println("new");          c1.f1();          c1.f2();          c1.f3();          System.out.println("c1 over");          c2.f1();          c2.f2();          c2.f3();            }

输出结果:

main start

A

A 0

C1 1

A 0

C2 8

new

C1 f1 0

C1 f3 5

C1 f3 super 5

A f3 5

c1 over

C2 f2 8

A f3 8

 

         从整体上来说,我们知道从对象的内存角度来说,假设现在有一个父类Father,它里面的变量需要占用1M内存.有一个它的子类Son,它里面的变量需要占用0.5M内存。

现在通过代码来看看内存的分配情况:

Father f = new Father();    //系统将分配1M内存.

Son s = new Son();    //系统将分配1.5M内存,因为子类中有一个隐藏的引用super会指向父类实例,所以在实例化子类之前会先实例化一个父类,也就是说会先执行父类的构造函数.由于s中包含了父类的实例,所以s可以调用父类的方法。

 

1.C1 c1 = new C1(0);对应输出了AA 0C1 1;先输出A,这点同时验证了子类先初始化父类,再执行父类构造函数A 0;再子类的构造函数C1 1

2.C2 c2 = new C2(0);对应输出了A 0C2 8;看出父类初始化只有一次,当构造函数必须在执行一次。

3.子类c1实现了自己的f1f2f3,使用时就是使用的自己的实现;子类c2没有实现f3,调用父类的实现。但是只使用父类的方法,数据成员还是自己的,所有输出“A f3 8”。


---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------详细请查看:http://edu.csdn.net
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机发热充电慢怎么办 饭盒盖子松了怎么办 饭盒盖子盖不住怎么办 饭盒盖子吸不住怎么办 饭盒盖子变形了怎么办 饭盒盖子凹进去怎么办 饭盒盖吸不住怎么办 饭盒微波炉加热后打不开怎么办 微波炉加热饭盒打不开怎么办 塑料饭盒加热后打不开怎么办 真空锅锅盖打不开怎么办 玻璃真空水壶打不开怎么办 保温饭盒盖子打不开怎么办 饭盒盖章松了怎么办 电压力锅卡住了怎么办 铁的饭盒打不开怎么办 微波炉饭盒盖子打不开怎么办 微波炉盖子吸住了怎么办 剩下的糯米饭怎么办 饭盒微波加热打不开怎么办 微波炉触屏不灵怎么办 微波炉旋钮坏了怎么办 微波炉蒸馒头硬怎么办 小猫两天不吃饭怎么办 减肥吃了巧乐兹怎么办 孕妇吃了点蟹籽怎么办 做寿司没有肉松怎么办 做寿司没有海苔怎么办 孩子不爱吃早餐怎么办 早上不想吃早餐怎么办 早上来不及吃早餐怎么办 早餐吃撑了怎么办 减肥吃撑了怎么办 哺乳吃爆米花了怎么办 干吃方便面后怎么办 吃了牛奶上火怎么办 绿豆糕吃多了怎么办 吃完火锅肚子烧怎么办 吃东西经常烫到怎么办 黄焖鸡酱料过期了怎么办 自热饭水弄错了怎么办