(10)Java学习笔记——面向对象04——继承

继承

继承的好处:

1/提高了代码的复用性

2/提高代码的维护性

3/让类与类之间产生了联系,给第三个特征多态提供了前提。(也是继承的一个弊端:类的耦合性增强)


开发的原则:低耦合,高内聚

耦合:类与类的关系

内聚:就是自己完成某件事情的能力


继承的基本格式(extends关键字

class  子类名  extends  父类名  {  }


范例1:

class Fu()
{
}

class Zi extends Fu	//通过关键字extends让子类继承父类
{
}

范例2:

class ExtendsDemo 
{
	public static void main(String[] args) 
	{
		Student s = new Student();
		s.name="zhangsan";
		s.age=20;
		s.study();
	}
}

class Person
{
	String name;
	int age;
}

class Student extends Person	//通过extends集成父类的属性
{
	void study()
	{
		System.out.println(name+"....student study...."+age);
	}
}

class worker extends Person		//通过extends集成父类的属性
{
	void work()
	{
		System.out.println(name+"....worker work...."+age);
	}
}


JAVA中继承的特点:

1 / Java中支持单继承,不直接支持多继承,但对C++中的多继承进行了改良。不直接支持多继承,是因为多个父类中有相同成员,会产生调用的不确定性。

单继承:一个子类只能有一个直接父类。


2 / Java支持多层(多重)继承。(C继承B,B继承A)就会出现继承体系。


继承的注意事项:

1 / 子类只能集成父类所有非私有的成员(包括成员变量和成员方法)

2 / 子类不能继承父类的构造方法,但是可以通过super来访问父类的构造方法。

3 / 不要为了部分功能去继承

4 / 


当要使用一个继承体系时:

1/查看该体系中的顶层类,了解该体系的基本功能。

2/创建体系中的最子类对象,完成功能的使用。


什么时候定义继承呢?

当类与类之间存在所属关系的时候,就定义继承。XXX是YYY中的一种,XXX extends YYY


————————————————————————————————————————————————————————————

继承中 成员(成员变量,构造方法,成员方法)的关系


继承者成员变量的关系:

a / 子类中的成员变量和父类中成员变量名称不一致。

b / 子类中的成员变量和父类中成员变量名称一样,会采用就近原则(就近原则的的先后顺序:先子类局部——>子类成员——>父类成员)。


调用成员变量的范例:

class Father	//父类
{
	int num = 10;
}

class Son extends Father	//子类继承父类
{
	int num = 20;

	public void show()
	{
		int num = 30; 
		System.out.println(num);	//采取的是就近原则。
	}
}

class ExtendsDemo 
{
	public static void main(String[] args) 
	{
		Son s = new Son();
		s.show();
	}
}

/*
结果是30
*/


this 和 super 的区别和应用

区别:

this 代表本类对应的引用。

super代表父类存储空间的标识(可以理解为父类引用,可以操作父类的成员)


如何调用:


a / 调用成员变量:

this . 成员变量 (表示调用本类的成员变量)

super . 成员变量 (表示调用父类的成员变量)


调用成员变量范例:

class Father	//父类
{
	int num = 10;
}

class Son extends Father	//子类继承父类
{
	int num = 20;

	public void show()
	{
		int num = 30; 
		System.out.println(num);	//采取的是就近原则。
		System.out.println(this.num);	//this访问的就是本类的成员(int num = 20;
		System.out.println(super.num);	//super访问的是父类存储空间的标识(可以理解为父类引用,可以操作父类的成员)
	}
}

class ExtendsDemo 
{
	public static void main(String[] args) 
	{
		Son s = new Son();
		s.show();
	}
}

/*
结果是30,20,10
*/


b / 调用构造方法

this (...)   (表示调用本类的构造方法)

super(....)   (表示调用父类的构造方法)


继承中构造方法的关系:

1 / 子类中所有的构造方法默认都会访问父类中空参数的构造方法

2 / 子类初始化之前,一定要先完成父类数据的初始化。然后才能继承父类中的数据。

3 / 子类的每一个构造方法的第一条语句默认都是:super();


调用构造方法的范例:

class Father
{
	public Father()	//Father无参构造方法
	{
		System.out.println("Father的无参构造方法");
	}

	public Father(String name)	//Father带参构造方法
	{
		System.out.println("Father的带参构造方法");
	}
}

class Son extends Father
{
	public Son()	//son的无参构造方法
	{
		System.out.println("son的无参构造方法");
	}

	public Son(String name)	//son的带参构造方法
	{
		System.out.println("son的带参构造方法");
	}
}


class ExtendsDemo2 
{
	public static void main(String[] args) 
	{
		Son s = new Son();
		System.out.println("------------------------");
		Son s1 = new Son("阿紫");
		
	}
}

/*
结果
Father的无参构造方法
son的无参构造方法
-------------------------
Father的无参构造方法	//说明子类默认访问父类空参数的构造方法
son的带参构造方法
*/


c / 调用成员方法

this . 成员方法  (表示调用本类的成员方法)

super . 成员方法  (表示调用父类的成员方法)


继承中成员方法的关系:

a / 子类中的方法和父类中的方法声明不一样。

b / 子类中的方法和父类中的方法声明一样。

通过子类对象调用方法的顺序:

---1 / 先找子类中看有没有这个方法,有就调用

---2 / 再看父类中有没有这个方法,有就调用,都没有就报错。

——————————————————————————————————————————————————————

方法重写:


子父类中的成员方法的特点:

当子父类中出现成员方法声明一模一样的情况(方法名,参数列表都一样),会运行子类的方法。

这种现象称为方法重写。这是方法在字符类中的特性。


方法的两个特性(仅方法有)

1/重载。同一个类中。(同一个类中,出现的方法名一样,参数列表不同的方法,且与返回值无关。)

2/重写。子类中。覆盖也称为重写,覆写。override  (当子父类中出现成员方法声明一模一样的情况(方法名,参数列表都一样))


方法重写注意事项:

1/子类方法覆盖父类方法是,子类权限必须要大于等于父类权限。

2/静态函数只能覆盖静态函数,或被静态函数覆盖。


什么时候使用覆盖操作?(方法重写的应用)

当对一个类进行子类的扩展是,子类需要保留父类的功能声明,

但是要定义子类中该功能的特有内容时,就使用覆盖操作完成。

范例:

class ExtendsTest01 
{
	public static void main(String[] args) 
	{
		NewPhone p = new NewPhone();
		p.call();
		p.show();
	}
}

class Phone
{
	void call()
	{
	}
	void show()
	{
		System.out.println("number");
	}
}

class NewPhone extends Phone	//子类内容是对父类的扩展
{
	void show()
	{
	System.out.println("name");
	System.out.println("pic");
	super.show();	//调用了父类的show方法
	}
}

方法重写的注意事项:

a / 父类中的私有方法不能被重写。

b / 子类重写父类方法是,访问权限不能更低。

c / 父类静态方法,子类也必须通过静态方法重写。


练习01:

使用继承前的学生和老师的案例:

/*
老师和学生案例

分析:
学生:
成员变量:名字,年龄
构造函数:无参,有参
成员方法:getXxx() / setXxx()

老师
成员变量:名字,年龄
构造函数:无参,有参
成员方法:getXxx() / setXxx()

*/

//定义学生类
class Student
{
	String name;
	int age;

	public Student()	//无参构造方法
	{
	}

	public Student(String name ,int age)	//带参构造方法
	{
		this.name = name;
		this.age = age;
	}

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

	public String getName()
	{
		return name;
	}

	public void setAge(int age)
	{
		this.age = age;
	}

	public int getAge()
	{
		return age;
	}
}

//定义一个老师类
class Teacher	
{
	String name;
	int age;

	public Teacher()
	{
	}

	public Teacher(String name ,int age)
	{
		this.name = name;
		this.age = age;
	}

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

	public String getName()
	{
		return name;
	}

	public void setAge(int age)
	{
		this.age = age;
	}

	public int getAge()
	{
		return age;
	}
}


class  ExtendsTest_01
{
	public static void main(String[] args) 
	{
		Student s1 = new Student();	//无参构造方法的方式
		s1.setName("阿朱");
		s1.setAge(26);
		System.out.println(s1.getName()+"----"+s1.getAge());

		System.out.println("-------------------------------");

		Student s2 = new Student("阿紫",27);	//带参构造方法的调用方式
		System.out.println(s2.getName()+"----"+s2.getAge());


	}
}


使用继承的学生和老师的案例:

/*
老师类和学生类相同部分向上抽取成person类,然后再继承person类

成员变量:名字,年龄
构造函数:无参
成员方法:getXxx()  /  setXxx()

*/

//定义一个person父类
class Person
{
	private String name;
	private int age;

	public Person()
	{
	}

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

	public String getName()
	{
		return name;
	}

	public void setAge(int age)
	{
		this.age = age;
	}

	public int getAge()
	{
		return age;
	}
}

//定义一个Student子类继承person父类
class Student extends Person
{
}

//定义要给Teacher子类继承Person父类
class Teacher extends Person
{
}

class ExtendsTest_02 
{
	public static void main(String[] args) 
	{
		Student s = new Student();
		s.setName("自尊宝");
		s.setAge(27);

		System.out.println(s.getName()+"----"+s.getAge());

		System.out.println("----------------------------");

		Teacher t = new Teacher();
		t.setName("紫霞仙子");
		t.setAge(26);

		System.out.println(t.getName()+"----"+t.getAge());

	
	}
}


练习02:

猫狗案例

/*
猫狗案例

猫有自己的特性playGame
狗友自己的特性lookHome

分析:
猫狗具有一致的特性,吃睡,可以定义一个父类进行继承

成员变量:吃,睡
构造函数:带参
成员方法:getXxx()  / setXxx()

不同的特性:

猫有自己的特性playGame
狗友自己的特性lookHome

*/

//定义一个父类,放置相同的共性
class Animal
{
	private String eat;
	private String sleep;

	public Animal(String eat, String sleep)	//定义了一个带参构造方法
	{
		this.eat = eat;
		this.sleep = sleep;
	}

	public void setEat(String eat)
	{
		this.eat = eat;
	}

	public String getEat()
	{
		return eat;
	}

	public void setSleep(String sleep)
	{
		this.sleep = sleep;
	}

	public String getSleep()
	{
		return sleep;
	}
	
}

//定义一个猫的类,继承animal
class Cat extends Animal
{
	public Cat(String eat,String sleep)	//定义了一个带参构造方法
	{
		super(eat,sleep);	//通过super指向父类的带参构造方法
	}

	public void playGame()	//定义一个方法,显示小猫特有的个性
	{
		System.out.println("小猫玩耍");
	}
}

//定义个一个狗的类,继承animal
class Dog extends Animal
{
	public Dog(String eat,String sleep)
	{
		super(eat,sleep);
	}

	public void lookHome()
	{
		System.out.println("小狗看家");
	}
}

class ExtendsTest_03 
{
	public static void main(String[] args) 
	{
		Cat c = new Cat("睡觉","吃鱼");
		System.out.println(c.getEat()+"----"+c.getSleep());
		c.playGame();

		System.out.println("----------------------------");

		Dog d = new Dog("睡觉","吃骨头");
		System.out.println(d.getEat()+"----"+d.getSleep());
		d.lookHome();
	}
}





一个对象的实例化过程:

Person p = new Person();

1/jvm会读取指定路径下的Person.class文件并加载进内存,并会先加载Person的父类(如果有直接父类的情况下)。

2/在对内存中开辟空间,分配地址值。

3/并在对象空间中,对对象中的属性进行默认初始化。

4/调用对应的构造函数进行初始化。

5/在构造函数中,第一行会先调用父类中的构造函数进行初始化。

6/父类初始化完毕后,再对子类的属性进行显示初始化。

7/再进行子类构造函数的特定初始化。

8/初始化完毕后,将地址值赋值给引用变量。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值