黑马程序员_Java面对对象——继承

------- android培训java培训、期待与您交流! ----------

一、 Java继承概述

            继承的关键字为extends.

           继承说的简单点有点子承父业的味道,就是子类一旦继承了父类,父类中所的成员变量和方法都可以被子类使用。

           继承的特点;

           1.        提高了代码的复用性。

           2.        让类产生了关系,有了这个关系,体现了多态的特性。

          继承的注意事项:

         1.        在Java中只能单继承,不支持多继承,即同时继承两个类;但有类似多继承的方式,叫做多实现。

         2.        在java中继承可以多重继承,也就是说B继承了A,C继承B之后就可以拥有A和B所有成员变量和方法,类似于沿袭,只要上一代有的我必须都有,所以这也叫做一个继承体系。

         3.        在Java中继承体系中的父类,都不是不断抽取子类的中共性内容得来的

         4.        在java中有一个超类,是所有类的父类,叫做object。

         5.        在Java中必须类与类有所属关系才可以继承,就像父子间的血缘关系,必须得有点联系才行,也就是父类中必须有子类中共性内容。

        在Java中不得为了获取其他类的功能达到简化代码的目的而继承。

        继承代码示例:

class ExtendsDemo 
{
	public static void main(String[] args) 
	{
		//创建子类对象
		Zi z = new Zi();
		z.setage(20);
		z.setname("gezi");
		//直接调用study方法
		z.study();
	}
}
//父类
class Fu
{
	private int age;
	private String name;
	//对外提供访问age的方法
	public void setage(int age)
	{
		if(age<130)
			this.age = age;
		else
			System.out.println("输入非法");
	}
	//对外提供得到age方法
	public int getage()
	{
		return age;
	}
	public void setname(String name)
	{
		this.name=name;
	}
	public String getname()
	{
		return name;
	}
	void study()
	{
		System.out.println("good good study"+"\n"+"name="+name+"\n"+"age="+age);
	}
}
//子类继承父类 就具备了父类中的所有成员特性 
class Zi extends Fu
{
	
}
二、 聚集关系

             在类与类之间不光有继承关系,还有聚集关系,具体的说就是聚合和组合关系。

             聚合:聚合关系就像一个球队,球队包括球员,球员有事球队中一个,但是少一个球员有不会对球队产生太大的影响。

             组合:组合关系就像水和鱼的关系,鱼离开水就不可生存,彼此密不可分。

三、 关键字super

              super关键字的用法与this一致,不一样的地方就是super是父类,this是本类,说的在明白点,就是super是指挥老子干活的,this指挥儿子干活的。

              子父类中成员变量的特点

                       在继承关系中,如果存在非私有且同名的成员变量时,父类的使用super关键字调用,子类的用this关键字调用。

class SuperDemo 
{
	public static void main(String[] args) 
	{
		//创建子类对象
		Zi z = new Zi();
		//调用子类方法
		z.show();
	}
}
class Fu
{
	int num = 5;
}
//子类继承父类
class Zi extends Fu
{
	int num = 10;
	void show()
	{
		//通过super关键字访问父类中的num,this关键字访问子类中的成员
		System.out.println(super.num+"……"+this.num);
	}
}

              子父类中函数的特点

                     方法重写(覆盖)

                          在继承关系,如果子父类中存在同名函数,默认会执行子类中函数,这种现象叫做重写(覆盖)。

                          在子类继承父类方法后,如果子类中拥有和父类相同功能,但功能内容不一致是,这时我们利用函数的覆盖特性,就父类中的方法覆盖掉,但如果想保留父类的功能,可以在覆盖的方法中,使用super关键字调用父类的方法,达到拓展功能的目的。

需要注意的是:

                   重写(覆盖)方法时,方法必须完全一样才能被覆盖。

                   当子类的权限大于等于父类是方法才会被覆盖。

                   静态函数也能被覆盖,但是静态只能覆盖静态。

                   注意:

                        方法重写不同于方法重载,重写必须两个方法完全一样,而重载只需要参数个数或者参数类型不同。

                        重写和重载功能类似,都是让同名函数具备不同的功能,但重写存在一定的局限性。

                        重写值发生在继承中,子类重写父类方法。

              子父类中构造函数的特点

                   1.        在子类对象初始化的时候,父类中的构造函数也会运行。

                               造成这个现象的主要原因就是所有子类的函数中,有一个隐式语句super();

                               super();必须出现在子类构造函数第一行,功能是访问父类中空参的构造函数。

                   2.        子类的构造函数中必须有访问父类函数的语句。

                              因为子类可以直接获取父类中的数据,所有在子类初始化对象之前,所有子类在初始化对象之前,要先查看一下父类是如何对这些数据初始化的,所以子类对象初始化之前必须要访问一下父类中的构造函数。

                  当然,如果需要访问非空参的父类够造函数时,就需要我们用super语句手动指定来访问父类中的哪个构造函数了。

                   super();语句只能出现在子类构造函数的第一行,且this语句不能同时使用。

                  继承弊端:打破了封装性,因为有继承关系发生,子类必然可以访问父类中的所有数据。
class  CoverDemo
{
	public static void main(String[] args) 
	{
		//创建子类对象并调用study()方法
		new Zi().study();
		Zi.show();
	}
}
class Fu
{
	Fu()
	{
		System.out.println("这是父类的构造函数");
	}
	int age = 20;
	String name = "gezi";
	void study()
	{
		System.out.println("name="+name+"age="+age+"FU");
	}
	static void show()
	{
		System.out.println("Fu");
	}
}
class Zi extends Fu
{
	Zi()
	{
		//默认的会先执行super();语句  访问父类中构造函数
		super();
		System.out.println("这是子类的构造函数");
	}
	//重写父类中的study方法
	void study()
	{
		System.out.println("name="+name+"\n"+"age="+age+"\n"+"ZI");
	}
	static void show()
	{
		System.out.println("Zi");
	}

}
四、 关键字final

                 格式:

                               final int PI=3.14;

                1.        Final可以修饰类、变量、函数。一旦被final修饰,就表示这是最终的形式,不可修改。

                2.        Final修饰类之后,类便不可被继承。不可以被继承。避免了被继承,被子类复写功能。

                3.        Final修饰方法之后,方法便不可被重写。

                4.        Final修饰变量之后,变量只能被赋一次值,所以可以修饰成员变量,也可以修饰局部变量,我们可以称之为常量。

                           当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,所以给这些值起个名字,便于阅读。

                            而这个值不需要改变,所以加上final修饰。

                           作为常量:常量的书写规范所有字母都大写,如果由多个单词组成单词间通过_连接。

               5.        内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。

六、 抽象类        关键字abstract

              抽象:抽象是从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征。

              可以理解为不具体、不明确、很模糊。

              抽象类的由来:

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

               抽象类的特点:

                     1.        抽象方法一定存在于抽象类中。

                     2.        在类中一旦出现抽象抽象方法,这个类也必然是抽象类,会被anstract修饰,系统默认添加,或者自己手动添加。

                     3.        在抽象类中可以没有抽象方法,如果类被abstract修饰,而类中没有方法被修饰,那么类就不能被创建对象。

                     4.        抽象类不能用new创建对象,因为调用抽象方法没意义。

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

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

           抽象类和普通类的区别:

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

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

                  这些不确定的部分,也是该事物的功能,需要明确出现。但是无法定义主体,通过抽象方法来表示。

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

                  抽象类不可以实例化。

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

             abstract 关键字,和哪些关键字不能共存?
                   final:被final修饰的类不能有子类。而被abstract修饰的类一定是一个父类。
                   private: 抽象类中的私有的抽象方法,不被子类所知,就无法被复写, 而抽象方法出现的就是需要被复写。
                   static:如果static可以修饰抽象方法,那么连对象都省了,直接类名调用就可以了。
        可是抽象方法运行没意义。

              抽象类中是否有构造函数?
                   有,抽象类是一个父类,要给子类提供实例的初始化。

           抽象类练习:

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

员工类:name id pay

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


*/
class AbstractDemo 
{
	public static void main(String[] args) 
	{
		//创建一个员工
		Person p = new Person("gezi","001",2000);
		p.work();
		//创建一个经理
		Manager m = new Manager("heima","002",3000,3000);
		m.work();
	}
}
//由员工类和经理类向上抽取的抽象类
abstract class Employee 
{
	private String name;
	private String pid;
	private int pay;
	Employee(){}
	//员工一入职就具备的属性
	Employee(String name,String pid,int pay){  

                    this.name = name;  

                    this.pid = pid;  

                    this.pay = pay;  

                }  
	public abstract void work();
}
//普通员工类继承员工类
class Person extends Employee
{
	//员工一入职就具备name/pid/pay属性
	Person(String name,String pid,int pay)
	{
		super(name,pid,pay);
	}
	//重写work方法
	public void work()
	{
		System.out.println("我是普通员工");
	}
}
//经理类继承员工类
class Manager extends Employee
{
	//经理特有的奖金
	private int bonus;
	Manager(String name,String pid,int pay,int bonus)
	{
		//super(name,pid,pay);
		//将值传给子类
		this.bonus=bonus;
	}
	public void work()
	{
		System.out.println("我是经理"+"bonus="+bonus);
	}
}

七、 模版方法设计模式

         什么是模板方法设计模式/

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

        例子:

            1、需求:获取一段程序运行的时间

            2、原理:获取程序开始和结束的时间并相减

            3、获取时间:System.currnetTimeMillis();

            4.代码实现

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

获取时间: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  Test
{
    public static void main(String[] args) 
    {
        //创建对象
        SubTime gt = new SubTime();
        //调用计时方法
        gt.getTime();
    }
}


八、 接口 

         接口的由来    

                   初期理解,可以认为是一个特殊的抽象类

         当一个抽象类中的所有方法都为抽象方法时,我们可以用另一种方式来体现,这就是接口。

         定义接口的关键字:interface

         定义接口的格式:interface{  }

         接口定义常量和方法的固定格式:

                   定义接口全局常量         public static final

                   定义接口抽象方法         public abstract

          结论:接口中的成员都是公共的权限,都是public。

          接口的注意事项:

                 接口是不可以创建对象的,因为有抽象方法。

            接口需要被子类实现(implements),子类对接口中的抽象方法全都覆盖后,子类才可以实例化,否则子类是一个抽象类。

          关键字:implements 实现

          接口可以被类多实现,也是对多继承不支持的转换形式。

           接口的特点:

           1.        接口是对外暴露的规则。

           2.        接口是程序的功能扩展。

           3.        接口的出现降低耦合性。

           4.        接口可以用来多实现。

           5.        类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。

           6.        接口与接口之间可以有继承关系。

          接口与抽象类的异同点:

               相同点:都是不断向上抽取而来的。

               不同点:

               1.        抽象类需要被继承,而且只能单继承。接口需要被实现,而且可以多实现。

               2.        抽象类中可以定义抽象方法和非抽象方法,子类继承后,可以直接使用非抽象方法。

               3.        接口中只能定义抽象方法,必须由子类去实现。

               4.        抽象类的继承,是is a关系,在定义该体系的基本共性内容。接口的实现是like a关系。

          注意:接口的属性都是常量,而且是全局常量,且接口中的方法都是抽象的。

class InterfaceDemo 
{
	public static void main(String[] args) 
	{
		//创建对象
		Demo d = new Demo();
		d.show();
		d.study();
		
	}
}
//定义一个接口
interface A
{
	//接口的成员变量全部为全局变量
	public static int NUM=10;
	//接口的方法都为抽象方法
	public abstract void show();
}
interface B
{
	public static double PI=3.14;
	public abstract void study();
}
//接口可以被多继承
class Demo implements A,B
{
	//重写接口方法
	public  void show()
	{
		System.out.println("我是接口A"+NUM);
	}
	public  void study()
	{
		System.out.println("我是接口B"+PI);
	}

}
关于接口的总结:

       接口就是程序的扩展功能,就像我们电脑的USB接口一样,可连接电脑和电脑外设,只要电脑和外设都符合接口就能使用这个接口实现功能的扩展。接口就是我们功能的主体和扩展功能的中间环节,类似一个协议。





------- android培训java培训、期待与您交流! ----------

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值