黑马程序员——java基础知识之面向对象(二)

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
javajia
(一)、面向对象之继承
1、什么是继承?
类与类之间存在了继承的关系。子类可以直接访问父类中的非私有的属性和行为。在代码中通过extends关键字表示继承关系。例:
class Sonextends Father{} //这也是在代码中的书写格式。

2、继承的作用
继承:提高了代码的复用性。
让类与类之间产生了关系。有了这个关系,才有了多态的特性。

3、注意
千万不要为了获取其他类的功能,简化代码而继承。
必须是类与类之间有所属关系才可以继承。所属关系 is a。

例子:

class C
{
    void demo1(){}
}


class A extends C
{
    //void demo1(){}
    void demo2(){}
}

class B extends C
{
    //void demo1(){}
    void demo3(){}
}

注意:在具体调用时,要创建最子类的对象。原因:
一是因为有可能父类不能创建对象。
二是创建子类对象可以使用更多的功能,包括基本的也包括特有的。

4、继承的应用
1、子父类出现后,类成员的特点:
类中成员:
①变量。
②函数。
③构造函数。

2、变量
1,变量
如果子类中出现非私有的同名成员变量时,
子类要访问本类中的变量,用this
子类要访问父类中的同名变量,用super。

super的使用和this的使用几乎一致。
this代表的是本类对象的引用。
super代表的是父类对象的引用。
例子:

class Fu 
{
    private int num = 4;
    public void setNum(int num)
    {
        this.num =num;
    }
    public int getNum()
    {
        return this.num;
    }
}

class Zi extends Fu
{
    int num = 5;
    void show()
    {
        System.out.println(num);
    }
}

class  ExtendsDemo2
{
    public static void main(String[] args) 
    {
        Zi z = new Zi();
        z.show();
        //System.out.println(z.num+"...."+z.num);
    }
}

3、子父类中的函数。
当子类出现和父类一模一样的函数时,
当子类对象调用该函数,会运行子类函数的内容。
如同父类的函数被覆盖一样。
这种情况是函数的另一个特性:重写(覆盖)

当子类继承父类,沿袭了父类的功能,到子类中,
但是子类虽具备该功能,但是功能的内容却和父类不一致,
这时,没有必要定义新功能,而是使用覆盖特殊,保留父类的功能定义,并重写功能内容。

注意:
覆盖:
1,子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。
2,静态只能覆盖静态。
记住大家:
重载:只看同名函数的参数列表。
重写:子父类方法要一模一样。

例子1:

class Fu
{
    void show()//父类定义show方法
    {
        System.out.println("fu show");
    }
    void speak()//父类定义speak方法
    {
        System.out.println("vb");
    }
}

class Zi extends Fu   //子类继承父类
{
    void speak()//子类重写父类speak方法
    {
        System.out.println("java");
    }
    void show()//子类重写父类show方法
    {
        System.out.println("zi show");
    }
}


class ExtendsDemo3 
{
    public static void main(String[] args) 
    {
        Zi z = new Zi();
        z.speak();

    }
}

4、子父类的构造函数的继承
也就是子类的实例化过程。
结论:
子类的所有的构造函数,默认都会访问父类中空参数的构造函数。
因为子类每一个构造函数内的第一行都有一句隐式super();

当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数。

当然:子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。
子类中至少会有一个构造函数会访问父类中的构造函数。
例子1:
基础测试题

package com.itheima;
/*
 * 有这样三个类,Person、Student、GoodStudent。
其中GoodStudent继承于Student,Student继承于Person。
如何证明创建GoodStudent时是否调用了Person的构造函数?
在GoodStudent中是否能指定调用Student的哪个构造函数?
在GoodStudent中是否能指定调用Person的哪个构造函数?
 */

/*
 * 解释说明:改程序运行的结果是:
 * 打印出:Person默认构造方法 证明:GoodStudent调用了Person的默认构造函数
        Student默认的构造方法  证明:GoodStuden调用了Student的默认构造函数  
        GoodStudent带参数的构造方法20110184 证明:GoodStudent不能指定调用Person的带参构造方法
 */
public class Test9 {
        public static void main(String[] args){

            //new一个GoodStudent类的对象,传的参数是20110184
            GoodStudent stu = new GoodStudent(20110184);
        }
    }

    class  Person{
        int id;

        //Person类的空构造方法
        public Person(){
            System.out.println("Person默认构造方法");
        }
        //Person类带参数的构造方法
        public Person(int id){
            System.out.println("Person带参数的构造方法"+id);
        }
    }

    class Student extends Person{
        int id;

        //Student类的空构造方法
        public Student(){
            System.out.println("Student默认的构造方法");
        }

        //Student类的带参数的构造方法
        public Student(int id){
            System.out.println("Student带参数的构造方法"+id);
        }
    }

    class GoodStudent extends Student{
        int id;

        //GoodStudent类的空构造方法
        public GoodStudent(){

例子2:

    int num ;
    Fu()
    {}
    Fu(int  x)
    {
        System.out.println("fu ...."+x);
    }   
}

class Zi extends Fu
{
    Zi()
    {       
        super();  
        System.out.println("zi run");
    }
    Zi(int x)
    {
        this();
        System.out.println("zi..."+x);
    }
}

class  ExtendsDemo4
{
    public static void main(String[] args) 
    {
        Zi z = new Zi(0);
        System.out.println(z.num);
    }
}

(二)、final关键字
final:是一个修饰符
作用:
1,可以修饰类,函数,变量。
2,被final修饰的类不可以被继承。为了避免被继承,被子类复写功能。
3,被final修饰的方法不可以被复写。
4,被final修饰的变量是一个常量只能赋值一次,既可以修饰成员变量,有可以修饰局部变量。
当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字。方便于阅读。
而这个值不需要改变,所以加上final修饰。作为常量:常量的书写规范所有字母都大写,如果由多个单词组成。
单词间通过_连接。
5,内部类定义在类中的局部位置上是,只能访问该局部被final修饰的局部变量。
例子:

class Demo
{
    final int x = 3;
    public static final double PI = 3.14;
    final void show1()
    {}
    void show2()
    {
        final int y = 4;
        System.out.println(3.14);
    }
}
class SubDemo extends Demo
{
    //void show1(){}
}
class FinalDemo 
{
    public static void main(String[] args) 
    {
        System.out.println("Hello World!");
    }
}

(三)、抽象类
1、什么是抽象?
抽取像的部分,当多个类中出现相同功能,但是功能主体不同,这是可以进行向上抽取。这时,只抽取功能定义,而不抽取功能主体。

2、抽象类的特点
抽象类的特点:
1,抽象方法一定在抽象类中。
2,抽象方法和抽象类都必须被abstract关键字修饰。
3,抽象类不可以用new创建对象。因为调用抽象方法没意义。
4,抽象类中的抽象方法要被使用,必须由子类复写起所有的抽象方法后,建立子类对象调用。
注意:如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。

抽象类和一般类没有太大的不同。
该如何描述事物,就如何描述事物,只不过,该事物出现了一些看不懂的东西。
这些不确定的部分,也是该事物的功能,需要明确出现。但是无法定义主体。
通过抽象方法来表示。

例子:

假如我们在开发一个系统时需要对员工进行建模,员工包含 3 个属性:
姓名、工号以及工资。经理也是员工,除了含有员工的属性外,另为还有一个
奖金属性。请使用继承的思想设计出员工类和经理类。要求类中提供必要的方
法进行属性访问。

员工类:name id pay

经理类:继承了员工,并有自己特有的bonus。


*/

class abtract Employee
{
    private String name;
    private String id;
    private double pay;

    Employee(String name,String id,double pay)
    {
        this.name = name;
        this.id = id;
        this.pay = pay;
    }

    public abstract void work();

}

class Manager extends Employee
{
    private int bonus;
    Manager(String name,String id,double pay,int bonus)
    {
        super(name,id,pay);
        this.bonus = bonus;
    }
    public void work()
    {
        System.out.println("manager work");
    }
}

class Pro extends Employee
{
    Pro(String name,String id,double pay)
    {
        super(name,id,pay);
    }
    public void work();

例子二:设计模板

/*
需求:获取一段程序运行的时间。
原理:获取程序开始和结束的时间并相减即可。

获取时间:System.currentTimeMillis();

当代码完成优化后,就可以解决这类问题。

这种方式,模版方法设计模式。

什么是模版方法呢?
在定义功能时,功能的一部分是确定的,但是有一部分是不确定,而确定的部分在使用不确定的部分,
那么这时就将不确定的部分暴露出去。由该类的子类去完成。


*/

abstract class GetTime
{
    public final void getTime()
    {
        long start = System.currentTimeMillis();
        //把位置的方法封装
        runcode();

        long end = System.currentTimeMillis();

        System.out.println("毫秒:"+(end-start));
    }
    //通过抽象类,让子类复写该方法
    public abstract void runcode();

}

//通过继承复写的功能,完成需求
class SubTime extends GetTime
{

    public void runcode()
    {

        for(int x=0; x<4000; x++)
        {
            System.out.print(x);
        }
    }
}


class  TemplateDemo
{
    public static void main(String[] args) 
    {
        //GetTime gt = new GetTime();
        SubTime gt = new SubTime();
        gt.getTime();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值