朝上 2022-01-15 02:32:10 阅读数:619
继承是面向对象的核心特性,是面向对象的学习重点。
继承是代码复用的重要方式,是类与类之间的一种关系。
从类与类之间的设计关系来看,子类必须属于父类的一种时,才会继承。
父类抽取出了共性的内容,子类可以在父类基础上扩展新的属性与行为。
子类拥有父类的所有属性与方法,无需重新定义。并且可以直接使用非私有的父类成员。
关键字 extends
父类
package com.igeek.javase.ch02.extendss;
/** * @version 1.0 * @Description TODO * * 继承: is-a * 1.关键字 extends * 2.继承本质上是设计层面的思想,本意是提高代码的复用性 * 3.子类继承父类后,父类中的成员变量和成员方法子类都具备,并且子类还可以拓展新的属性和新的方法 * 4.创建的父类对象,可以使用父类中的成员属性和成员方法,但是不能使用子类拓展的属性及方法 * 5.Java中类与类之间是单继承 */
public class Animal {
private String name;
private String color;
private int age;
public Animal() {
}
public Animal(String name, String color, int age) {
this.name = name;
this.color = color;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//吃
public Animal eat(/*Animal a*/) /*throws Exception*/{
System.out.println("一只"+color+name+"在吃东西...");
return null;
}
}
子类
package com.igeek.javase.ch02.extendss;
/** * @version 1.0 * @Description TODO */
public class Dog extends Animal{
//
private String player;
public Dog() {
}
public Dog(String name, String color, int age, String player) {
super(name, color, age);
this.player = player;
}
public String getPlayer() {
return player;
}
public void setPlayer(String player) {
this.player = player;
}
//
public void kanjia(){
System.out.println("一只"+this.getAge()+"的"+this.getName()+"在看家...");
}
}
当父类的成员变量用private修饰后,子类无法访问父类的成员变量,但是如果父类提供了public修饰的get/set方法,则子类可以通过get/set方法,正常访问父类的成员变量。
当子类继承父类后,拥有了父类的成员并可以直接调用父类非私有方法。如果子类认为父类提供的方法不够强大,子类可以按照子类自身的逻辑重新定义继承过来的父类方法,这个重新定义父类方法的过程叫做方法重写。
方法重写后,调用该方法时不再调用父类的方法,而调用子类重写后的方法。
package com.igeek.javase.ch02.extendss;
/** * @version 1.0 * @Description TODO * * 方法重载 Overload * 1.发生在一个类中 * 2.方法名相同 * 3.参数列表不同(参数个数、参数顺序、参数数量不同) * 4.与返回值无关 * * 方法重写 Override * 1.发生在继承中,子类继承父类,子类重写父类的方法 * 2.方法名相同 * 3.形参必须一致 * 4.返回值:若是基本数据类型则返回值一致即可; * 若是引用数据类型,则子类的返回值类型不可以放大,只可以是<=父类的返回值类型 Object>Animal>Cat 父类>子类 * 5.访问权限修饰符:子类是不可以缩小范围的 public>protected>(default)>private * 6.抛出异常:子类抛出异常比父类小 Throwable>Exception>NullPointerException * * 注意: * [email protected]一旦标注在方法上,检测当前方法是否符合重写要求 * 2.子类重写父类的方法后,调用执行时会执行子类重写后的逻辑 */
public class Cat extends Animal{
public Cat() {
}
public Cat(String name, String color, int age) {
super(name, color, age);
}
//捕捉方法
public void zhua(){
System.out.println("一只"+this.getAge()+"岁的,小"+this.getName()+"在抓鱼...");
}
// Alt+Insert -> Override 或者 Ctrl+O
@Override
public Cat eat(/*Animal a*/) /*throws NullPointerException*/{
Cat cat = new Cat();
//默认调用父类的逻辑
//super.eat();
System.out.println("一只"+getName()+"在吃鱼...");
return cat;
}
}
Test
package com.igeek.javase.ch02.extendss;
/** * @version 1.0 * @Description TODO */
public class Test {
public static void main(String[] args) {
Cat cat = new Cat("小猫咪","花色",2);
cat.eat(); //Cat中方法重写eat(),执行时会按照子类的逻辑进行执行
cat.zhua();
System.out.println("------------------");
Tiger tiger = new Tiger();
tiger.setName("东北虎");
tiger.setColor("白色");
tiger.setAge(3);
tiger.eat();
tiger.hunt();
System.out.println("------------------");
Dog dog = new Dog("哈士奇","灰色",5,"彩钢儿");
dog.eat();
dog.kanjia();
System.out.println("------------------");
Animal animal = new Animal("动物","无色",1);
animal.eat();
//animal.hunt();
//animal.kanjia();
//animal.zhua();
}
}
输出
一只小猫咪在吃鱼...
一只2岁的,小小猫咪在抓鱼...
------------------
一只白色东北虎在吃东西...
东北虎在狩猎中...
------------------
一只灰色哈士奇在吃东西...
一只5的哈士奇在看家...
------------------
一只无色动物在吃东西...
1.成员变量、成员方法 可以继承
2.私有的属性 可以继承
3.静态的成员 不可以继承,静态成员是所有实例共享
4.构造方法 不可以继承
1.成员变量不存在重写的问题
2.构造方法 不可以重写
3.静态方法 不可以重写
4.私有方法 不可以重写
在每次创建子类对象时,我们均会先初始化父类内容,再初始化其子类本身内容。目的在于子类对象中包含了其对应的父类存储空间,便可以包含了其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。
代码体现在子类的构造方法调用时,一定先调用父类的构造方法。
调用普通成员:
this.成员变量 可以访问本类对象的成员变量
super.成员变量 可以访问父类的成员变量
this.成员方法() 可以访问本类对象的成员方法
super.成员方法() 可以访问父类的成员方法
子类方法中
访问子类自身的成员用this.
访问父类的成员super.
就近原则:
局部 > 本类成员 > 父类成员
调用构造方法:
this(其他参数) 可以访问本类其他的构造方法
super(其他参数) 可以访问父类其他的构造方法
默认子类调用父类构造方法:
子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super();
在子类构造中使用this() 或 this(参数类型 参数值…)的方法可以调用本类中的其他构造方法。但是最终都是要调用父类的构造方法,完成父类成员的初始化。
对象和对象之间的连接。在Java中,关联关系的代码表现形式为一个类做为另一个类的属性类型存在。即“有”的关系:”has-a”。
1.代码层面:一个类作为另外一个类的属性类型存在
2.has-a 有
3.一对一 、 一对多Phone[] phones、List<Phone> list
4.强关联(组合关系)、弱关联(聚合关系)
5.单向关联、双向关联
package com.igeek.javase.ch02.has;
import java.util.Arrays;
/** * @version 1.0 * @Description 关联关系 */
public class ClassTest {
public static void main(String[] args) {
Student stu1 = new Student("小红",100);
Student stu2 = new Student("小黑",101);
Student stu3 = new Student("小白",102);
Student[] stus = {
stu1,stu2,stu3};
Classes classes = new Classes("Java","班级1",stus);
// classes.setStudents(stus);
stu1.setClasses(classes);
stu2.setClasses(classes);
stu3.setClasses(classes);
//双向关联中 , toString()会互相调用的问题,造成堆栈溢出错误 , 一定要注意
System.out.println(classes);
System.out.println("-----------"+classes.getName()+"的学生信息如下------------");
for (Student student : classes.getStudents()) {
System.out.println(student);
}
}
}
class Classes{
private String label;
private String name;
//一对多 强关联 双向关联
private Student[] students = new Student[3];
public Classes() {
}
public Classes(String label, String name) {
this.label = label;
this.name = name;
}
public Classes(String label, String name, Student[] students) {
this.label = label;
this.name = name;
this.students = students;
}
/** * 获取 * @return label */
public String getLabel() {
return label;
}
/** * 设置 * @param label */
public void setLabel(String label) {
this.label = label;
}
/** * 获取 * @return name */
public String getName() {
return name;
}
/** * 设置 * @param name */
public void setName(String name) {
this.name = name;
}
/** * 获取 * @return students */
public Student[] getStudents() {
return students;
}
/** * 设置 * @param students */
public void setStudents(Student[] students) {
this.students = students;
}
/*public String toString() { return "Classes{label = " + label + ", name = " + name + ", students = " + Arrays.toString(students) + "}"; //StackOverflowError 堆栈溢出 }*/
public String toString() {
return "Classes{label = " + label + ", name = " + name + "}";
}
}
class Student{
private String name;
private int num;
//一对一 弱关联 双向关联
private Classes classes;
public Student() {
}
public Student(String name, int num) {
this.name = name;
this.num = num;
}
public Student(String name, int num, Classes classes) {
this.name = name;
this.num = num;
this.classes = classes;
}
/** * 获取 * @return name */
public String getName() {
return name;
}
/** * 设置 * @param name */
public void setName(String name) {
this.name = name;
}
/** * 获取 * @return num */
public int getNum() {
return num;
}
/** * 设置 * @param num */
public void setNum(int num) {
this.num = num;
}
/** * 获取 * @return classes */
public Classes getClasses() {
return classes;
}
/** * 设置 * @param classes */
public void setClasses(Classes classes) {
this.classes = classes;
}
public String toString() {
return "Student{name = " + name + ", num = " + num + ", classes = " + classes + "}";
}
}
依赖关系(use-a):指一个类A使用到了另一个类B。依赖关系的特性:这种关系是具有偶然性的、临时性的、非常弱的,但是类B的变化会影响到类A。
1.代码层面 一个类作为另外一个类的方法形参类型存在
2.use-a 用
3.具备临时性,偶然性
public class Person {
private String name;
//上班的方法 类A使用到了另一个类B
public void work(Bus bus){
System.out.println(this.name+"乘坐"+bus.getName()+"去上班");
}
public Person() {
}
public Person(String name) {
this.name = name;
}
/** * 获取 * @return name */
public String getName() {
return name;
}
/** * 设置 * @param name */
public void setName(String name) {
this.name = name;
}
public String toString() {
return "Person{name = " + name + "}";
}
}
版权声明:本文为[朝上]所创,转载请带上原文链接,感谢。 https://blog.csdn.net/m0_51051154/article/details/120096186