黑马程序员--Java的继承和实现

JAVA的继承与实现


一、继承


什么是继承

在程序中,可以使用extends关键字让一个类继承另外一个类。
继承的类为子类(派生类),被继承的类为父类(超类, 基类)。
子类会自动继承父类所有的方法和属性。

为什么要使用继承

当我们发现一个类的功能不行,方法不够用时,就可以派生子类,增加方法。
当我们需要定义一个能实现某项特殊功能的类时,就可以使用继承。
最终还是为了一个目的,提高代码的复用性。

当我们定义一个类时,发现另一个类的功能这个类都需要,而这个类又要增加一些新功能时,
就可以使用extends关键字继承那个类,这样那个被继承类的功能就都有了,不必重写编写代码。
这时只要在新的类中编写新的功能即可,原有代码就被复用了。

继承的特点

Java只支持单继承,不支持多继承,但是可以多重继承
因为如果一个类继承多个类,多个类中有相同的方法,子类调用该方法时就不知道该调用哪一个类中的方法了。


 (1)把多个类中的相同的属性和行为进行抽取,封装到一个类中,
    然后再建立新类的时候,不需要从头做起,继承刚才定义的那个类即可。
 (2)好处:
  A:提高代码的复用性。
  B:让类与类之间产生了一个关系,是多态的前提。
 (3)什么时候使用继承?
  A:如果类之间存在着:
   is a 的关系,就可以考虑使用继承。
  B:不要为了继承部分功能,而去使用继承。
 (4)继承的特点:
  A:Java只支持单继承,不支持多继承。
   为什么?如果支持多继承,就会有调用不明确的问题。
  B:Java支持多层(重)继承。
 (5)super和this的区别?
  A:super是一个关键字,代表父类的存储空间标识。(可以理解为父亲的引用)
  B:它和this的用法相似
   a:成员变量
    this.变量 -- 本类的
    super.变量 -- 父类的
   b:构造方法
    this(...) -- 本类的
    super(...) -- 父类的
   c:成员方法
    this.方法名() -- 本类的 
    super.方法名() -- 父类的
 (6)子父类中成员变量的用法:
  A:名称不同,这个太简单了。
  B:名称相同,子类对象的在使用的时候:
   
   先找子类局部范围
   再找子类成员范围
   最后找父类成员范围
 (7)子父类中成员方法的用法:
  A:名称不同,这个太简单了。
  B:名称相同,子类对象的在使用的时候:
   先找子类的
   再找父类的
  C:方法重写
   在子类中,方法声明(修饰符,返回值,方法名,参数列表)相同的情况。

   注意事项:
    a:父类中私有方法是不能被重写
    b:子类方法的访问权限一定要大于等于父类的访问权限
    c:静态只能重写静态。(这个不能算,因为静态跟类相关)
 (8)子父类中构造方法的用法:
  A:子类的初始化过程中,首先回去执行父类的初始化动作。
     因为子类的构造方法中默认有一个super()。
   为什么?子类要使用父类的成员变量,这个初始化,必须在子类初始化之前完成。
   所以,子类的初始化过程中,会先执行父类的初始化。
  B:如果父类没有无参构造方法
   A:使用super调用父类的带参构造。推荐方式。
   B:使用this调用本身的其他构造。


用一段代码说明其结构

class Person
 {
  private String name;
  private int age;

  public Person(){}

  public void setName(String name)
  {
   this.name = name;
  }

  public String getName()
  {
   return name;
  }

  ...
 }

 class Student extends Person
 {
 
 }

 class Teacher extends Person
 {
 
 }

叫法:
 Person:父类,基类,超类。
 Student,Teacher:子类,派生类。

注意:
 子类可以直接访问父类中的非私有的属性和行为。


继承的内存图示:


二、继承的好处


继承的好处:
  A:提高了代码的复用性。
  B:让类与类之间产生了一个关系,是多态的前提。

 继承的特点:
  A:Java只支持单继承,不支持多继承。
   为什么呢?因为如何可以多继承,就会出现调用不明确的问题。
  B:Java支持多层(重)继承(继承体系)

 什么时候把类的关系定义为继承呢?
  由于继承体现了一种关系:is a的关系。xxx is yyy的一种。
  以后,你在定义类(A,B)的时候:
   如果他们有关系:A is a B 的一种。或者B is a A。
   那么,他们之间就存在继承关系。前者A是子类,后者B是子类。

  注意:不要为了获取部分功能,而去使用继承。


{
	public void show()
	{
		System.out.println("person");
	}
}

/*
class School
{
	public void show()
	{
		System.out.println("school");
	}
}
*/

//class Student extends Person,School
class Student extends Person
{
	public void method()
	{
		System.out.println("method");
	}
}

class Coder extends Student
{

}

class ExtendsDemo2
{
	public static void main(String[] args)
	{
		Person p = new Person();
		p.show();
		System.out.println("------");

		Student s = new Student();
		s.show();
		s.method();
		System.out.println("------");

		Coder c = new Coder();
		c.show();
		c.method();
	}
}


继承中的一些构造方法


继承中的构造关系:
  子类的构造方法默认都去访问了父类的无参构造方法:
   在子类中的构造方法中都有一行默认语句:super()
  
  为什么要这样呢?
   因为子类会自动具备父类中非私有数据,那么,这个数据的初始化
   靠父类完成。所以,会去先调用父类的构造方法对数据进行初始化。

 注意:
  如果父类中没有无参构造方法,那么,该怎么办呢?
  A:可以通过super(参数)去访问父类中的带参构造方法。
  B:可以通过this(参数...)去访问本类中的其他构造方法。不推荐使用。

 思考:
  构造方法是否有重写关系?(面试题) 不能,构造方法要和类名相同。

class Fu
{
	public Fu()
	{
		System.out.println("fu");
	}
}

class Zi extends Fu
{
	public Zi()
	{
		super();
		System.out.println("zi");
	}	
}

class ExtendsDemo6
{
	public static void main(String[] args)
	{
		Zi z = new Zi();
	
	}
}


子父类方法的重写问题

A:父类中的私有方法不可以被重写。
B:子类方法访问权限一定要大于等于父类方法访问权限
C:静态的方法只能被静态方法重写。这个其实不能算对象的关系。
D:覆盖的应用:
   当子类需要父类的功能,而功能主体子类有自己特有内容时,
   可以复写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容。


class Phone
{
	private void show()
	{
		System.out.println("private phone");
	}

	/*
	public void method()
	{
		System.out.println("method Phone");
	}
	*/

	public void method()
	{
		System.out.println("method Phone");
	}

	public static void function()
	{
		System.out.println("function Phone");
	}

	public void call()
	{
		System.out.println("打电话");
	}
}

class NewPhone extends Phone
{
	public void method()
	{
		System.out.println("method NewPhone");
	}

	public static void function()
	{
		System.out.println("function NewPhone");
	}

	public void call()
	{
		System.out.println("播放彩铃");
		//System.out.println("打电话");
		super.call();
	}
}

class ExtendsDemo5 
{
	public static void main(String[] args) 
	{
		NewPhone np = new NewPhone();
		np.call();
	}
}


多态


 (1)对象在不同时刻表现出来的不同状态。
  举例:猫(猫、宠物、动物)
 (2)多态的前提
  A:要有继承或者实现关系。
  B:要有方法的重写。
  C:要有父类引用或者父接口引用指向子类对象。

  注意:多态有三种体现形式
   类多态
   抽象类多态
   接口多态
 (3)多态中的成员特点:
  A:成员变量
   编译看左边,运行看左边。
  B:成员方法
   编译看左边,运行看右边。

  为什么?因为方法存在重写,而变量没有。

  举例:孔子装爹。
 (4)多态的弊端:
  父类(接口)引用不能使用子类特有功能。
  为了解决这个弊端,我们需要向下转型。

  Fu f = new Zi(); //向上转型
  Zi z = (Zi)f; //向下转型

  Zi z = new Zi();
 (5)多态的好处:
  可以提高代码的扩展性和可维护性。


class Fu
{
	public int num = 10;

	public void show()
	{
		System.out.println("fu show");
	}
}

class Zi extends Fu
{
	public int num = 20;

	public void show()
	{
		System.out.println("zi show");
	}

	public void method()
	{
		System.out.println("zi method");
	}
}

class DuoTaiDemo2 
{
	public static void main(String[] args) 
	{
		/*
		Fu f = new Fu();
		f.show();
		System.out.println(f.num);

		Zi z = new Zi();
		z.show();
		System.out.println(z.num);
		*/

		//多态
		Fu fu = new Zi();
		fu.show();//zi show
		//fu.method();
		System.out.println(fu.num);//10
		//System.out.println(fu.num2);
	}
}


三、接口实现


 (1)如果一个抽象类中的方法都是抽象的,这个时候,java就提供了一种
    更抽象的表示形式:接口。
    接口:interface
    实现:implements

    格式:
  interface 接口名{}

  class 类名 implements 接口名 {}
 (2)接口的特点:
  A:接口不能被实例化。
  B:一个类如果实现了接口:
   要么是抽象类。
   要么实现接口中的所有方法。
 (3)接口的成员特点:
  A:成员变量 只能是常量。默认修饰符 public static final
  B:成员方法 只能是抽象方法。默认修饰符 public abstract

  推荐:永远手动给出修饰符。
 (4)接口的思想特点:
  A:对外暴露的规则
  B:是功能的扩展
  C:降低耦合度
   耦合:类与类的关系
   内聚:类自己完成某件事情的能力

   高内聚,低耦合。
  D:接口可以多实现。
 (5)类,接口的关系
  A:类与类
   继承关系,只能单继承,可以多层继承。
  B:类与接口
   实现关系,可以单实现,也可以多实现。
   还可以在继承一个类的同时实现多个接口。
  C:接口与接口
   继承关系,可以单继承,也可以多继承。
 (6)抽象类和接口的关系?自己补齐。
                接口是一种特殊的抽象类,比抽象类更抽象,因为它里
 (7)案例:运动员和教练的案例。

接口的成员特点:
  成员变量:接口中只有常量。
      因为接口的成员变量有默认修饰符:
     public static final
     推荐:永远自己给出修饰符。
  构造方法:
      没有构造方法。
      任何类如果没有继承父类,那么这个类就继承自Object类。
  成员方法:接口中的方法都是抽象的。
      因为接口中的成员方法有默认修饰符:
     public abstract
     推荐:永远自己给出修饰符。

interface Animal
{
	int num = 100;
	public int x = 10;
	public final int y = 20;

	//public Animal(){}

	//public void method();
	//abstract void method();
	public abstract void method();
}

class Dog implements Animal
{

	public Dog()
	{
		super();
	}

	public void show()
	{
		//x = 30;
		System.out.println(x);
		System.out.println(y);
		System.out.println(Animal.x);
		System.out.println(Animal.y);
	}
	
	public void method()
	{
		System.out.println("dog method");
	}
}

class InterfaceDemo2 
{
	public static void main(String[] args) 
	{
		Dog d = new Dog();
		d.show();
	}
}








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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值