【0基础学java】教学日志:javaSE-面向对象4-继承、super、方法重写、抽象类、抽象方法、final、Object类


本章概述 本章属于面向对象第三章的内容,主要讲解继承、super、方法重写、抽象类、抽象方法、final、Object类等知识点。
?一、继承   ? 1、为什么要使用继承? 使用继承优化后:   ?子类和父类是is-a的关系 2、继承是什么?
  • 类是对对象的抽象,继承是对某一批类的抽象,从而实现对现实世界更好的建模。
  • 提高代码的复用性!
  • extends的意思是“扩展”。子类是父类的扩展
  • 不同的叫法:超类、父类、基类、子类、派生类
3、如何使用继承? 使用继承 --编写父类 --编写子类,继承父类 --一个类只能继承一个父类 4、课堂Demo【重点掌握】 子类 Dog.java package netclass03.extend; /** * @Auther: Yu Panpan * @Date: 2022/1/10 - 01 - 10 - 15:24 * @Description: netclass03.extend * @version: 1.0 */ public class Dog extends Pet { // private String name; // private int age; // private String gender; private String sound; public Dog(){ // super(); } // public Dog(String name){ // super(name); // } // // public Dog(int age,String gender){ // super(age,gender); // } public Dog(String name, int age, String gender, String sound) { // super(); // super(name); // this(age,gender); super(name,age,gender); // this.name = name; // this.age = age; // this.gender = gender; this.sound = sound; } // public String getName() { // return name; // } // // public void setName(String name) { // this.name = name; // } // // public int getAge() { // return age; // } // // public void setAge(int age) { // this.age = age; // } // // public String getGender() { // return gender; // } // // public void setGender(String gender) { // this.gender = gender; // } public String getSound() { return sound; } public void setSound(String sound) { this.sound = sound; } public void show(){ // System.out.println("name:" +this.name +" age:" +this.age +" gender:" +this.gender +" sount:" +this.sound); System.out.println("name:" +this.getName() +" age:" +this.getAge() +" gender:" +this.getGender() +" sount:" +this.sound); } @Override public void print(){ System.out.println("Dog print... ..."); // super.print(); } } ?子类 Penguin.java package netclass03.extend; /** * @Auther: Yu Panpan * @Date: 2022/1/10 - 01 - 10 - 15:25 * @Description: netclass03.extend * @version: 1.0 */ public class Penguin extends Pet { // private String name; // private int age; // private String gender; private String color; public Penguin(){ } public Penguin(String name, int age, String gender, String color) { super(name,age,gender); // this.name = name; // this.age = age; // this.gender = gender; this.color = color; } // public String getName() { // return name; // } // // public void setName(String name) { // this.name = name; // } // // public int getAge() { // return age; // } // // public void setAge(int age) { // this.age = age; // } // // public String getGender() { // return gender; // } // // public void setGender(String gender) { // this.gender = gender; // } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public void show(){ // System.out.println("name:" +this.name +" age:" +this.age +" gender:" +this.gender +" color:" +this.color); System.out.println("name:" +this.getName() +" age:" +this.getAge() +" gender:" +this.getGender() +" color:" +this.color); } } 父类Pet.java package netclass03.extend; /** * @Auther: Yu Panpan * @Date: 2022/1/10 - 01 - 10 - 15:33 * @Description: netclass03.extend * @version: 1.0 */ public class Pet { private String name; private int age; private String gender; public Pet(){ // super(); //指向顶级父类Object System.out.println("Pet 空构造器... ..."); } // public Pet(String name){ // this.name= name; // } // // public Pet(int age,String gender){ // this.age = age; // this.gender = gender; // } public Pet(String name, int age, String gender) { System.out.println("Pet(String name, int age, String gender)... ..."); this.name = name; this.age = age; this.gender = gender; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public /*static*/ void print(){ System.out.println("Pet print... ..."); } private void test(){ System.out.println("Pet test... ..."); } } 测试类PetTest.java package netclass03.extend; /** * @Auther: Yu Panpan * @Date: 2022/1/10 - 01 - 10 - 15:25 * @Description: netclass03.extend * @version: 1.0 */ /* * 继承: * 表示父类跟子类之间的关系 * 当两个类或者多个类具备相同的属性和方法的时候,可以提取出来,变成父类,子类可以继承 * * 子类跟父类是is-a的关系 * * 使用: * 1、使用继承的时候需要使用extends关键字 * 2、使用继承关系之后,父类中的属性和方法都可以在子类中进行使用(非私有属性和非私有方法) * 3、java中是单继承关系(如果包含多个父类,同时父类中包含重名方法,无法决定该调用谁) * * * super:是 直接父类 对象的引用 * 用途: * 1、可以在子类中调用父类中被子类覆盖的方法 super.父类方法名称 * 2、当super在普通方法中使用的话,可以任意位置编写 * 3、当super在构造方法中使用的话,会调用父类的构造方法,一定要将super放在第一行 * 4、在构造方法中super关键字和this关键字(指的是不能同时使用this关键字调用重载的构造方法)不能同时出现 * 5、父类中私有的属性和方法都不能被调用,包括构造方法 * 6、子类的构造方法中都会默认使用super关键字调用父类的无参构造方法,因此在定义类的时候,无论自己是否自定义了 * 其他构造方法,最好将无参构造方法写上 * 7、如果构造方法中显式的指定了super的构造方法,那么无参的构造方法就不会被调用 * * 总结: * 1、在创建子类对象的时候一定会优先创建父类对象 * 2、所有的java类都具备同一个顶级父类(老祖宗),称之为Object,是所有类的根类 * * 重写:(覆盖)override * 必须要存在继承关系,当父类中的方法无法满足子类需求的时候可以选择使用重写的方式 * 注意: * 1、重写表示的是子类覆盖父类的方法,当覆盖之后,调用同样的方法的时候会优先调用子类 * 2、重写的方法名称,返回值类型,参数列表必须跟父类一致 * 3、子类重写的方法不允许比父类的方法具备更小的访问权限 * 父类 public 子类 public * 父类 protected 子类 public protected * 父类 default 子类 public protected default * 父类的静态方法子类可以进行调用,但是子类不可以重写 * */ public class PetTest { public static void main(String[] args) { // Dog dog = new Dog(); // dog.name = "xiaohei"; // dog.setName("小白"); // dog.setAge(10); // dog.setGender("雄性"); // dog.setSound("汪汪汪~~"); // dog.show(); // dog.print(); Dog dog = new Dog("小白",10,"雄性","汪汪汪~~"); dog.print(); // dog.name = "小黑"; // dog.test(); // Dog dog = new Dog(); // Penguin p = new Penguin("小白",11,"雌性","olive"); // p.show(); } } 2、java中只有单继承,也就是从子类出发只能有一个直接父类。课堂代码【重点掌握】 父类1--Father1.java package netclass03.extend; /** * @Auther: Yu Panpan * @Date: 2022/1/10 - 01 - 10 - 16:12 * @Description: netclass03.extend * @version: 1.0 */ public class Father1 { public void test(){ System.out.println("Father1 test... ..."); } } 父类2--Father2.java package netclass03.extend; /** * @Auther: Yu Panpan * @Date: 2022/1/10 - 01 - 10 - 16:12 * @Description: netclass03.extend * @version: 1.0 */ public class Father2 { public void test(){ System.out.println("Father2 test... ..."); } } 子类--SubClassTest.java package netclass03.extend; /** * @Auther: Yu Panpan * @Date: 2022/1/10 - 01 - 10 - 16:13 * @Description: netclass03.extend * @version: 1.0 */ public class SubClassTest extends Father1/*,Father2*/ { public static void main(String[] args) { // Father1 father1 = new Father1(); // father1.test(); SubClassTest sct = new SubClassTest(); sct.test(); } } 3、其他代码--课堂Demo【重点掌握】 PetClassTest.java package netclass03; import netclass03.extend.Pet; /** * @Auther: Yu Panpan * @Date: 2022/1/10 - 01 - 10 - 17:01 * @Description: netclass03 * @version: 1.0 */ public class PetClassTest extends Pet { public static void main(String[] args) { PetClassTest pct = new PetClassTest(); pct.print(); } } Tiger.java--演示在类中创建set,get方法时,如果出现boolean类型的成员变量,get方法要以is开头。 package netclass03; /** * @Auther: Yu Panpan * @Date: 2022/1/10 - 01 - 10 - 14:54 * @Description: netclass03 * @version: 1.0 */ public class Tiger { private String name; private int age; private boolean isAnimal; public Tiger(){ } public Tiger(String name, int age, boolean isAnimal) { this.name = name; this.age = age; this.isAnimal = isAnimal; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public boolean isAnimal() { return isAnimal; } public void setAnimal(boolean animal) { isAnimal = animal; } } 二、继承的理解和super【课堂Demo同上】 1、super是直接父类对象的引用。 2、可以通过super来访问父类中被子类覆盖的方法或属性。 3、普通方法: 没有顺序限制。可以随便调用。 4、构造函数中: 任何类的构造函数中,若是构造函数的第一行代码没有显式的调用super(...);那么 Java默认都会调用super();作为父类的初始化函数。 所以你这里的super();加不加 都无所谓。 5、super实例代码 public class Test { public static void main(String[] args) { new ChildClass().f(); } } class FatherClass { public int value; public void f(){ value = 100; System.out.println ("FatherClass.value="+value); } } class ChildClass extends FatherClass { public int value; public void f() { super.f(); value = 200; System.out.println("ChildClass.value="+value); System.out.println(value); System.out.println(super.value); } } ? 6、理解继承: a、子类访问父类成员 使用super关键字代表父类对象 ---- 访问父类构造方法 super(); super(name); 在子类构造方法中调用且必须是第一句 ---- 访问父类属性 super.name; ---- 访问父类方法 super.print(); b、子类可以继承父类的所有资源吗? 不能被继承的父类成员有哪些? ---- 不能直接访问private成员 ---- 子类与父类不在同包,使用默认访问权限的成员 ---- 构造方法不能被继承 c、访问修饰符protected ---- 可以修饰属性和方法 ---- 本类、同包、子类可以访问 d、访问修饰符总结   ? e、多重继承关系的初始化顺序是怎样的? 1、父类属性---->2、父类构造方法---->3、子类属性---->4、子类构造方法 f、理解继承示例代码 ?public class TestExtends { public static void main(String[] args) { Mammal m1 = new Mammal(); m1.puru(); m1.eat(); } } class Animal { String eyes="眼睛"; String name="无名"; public void eat(){ System.out.println("动物吃东西!"); } } class Mammal extends Animal { //哺乳 public void puru(){ eyes=“嘴巴”; System.out.println("小动物吃奶!"); } } g、在何处使用继承? 何时使用继承? ---- 继承和真实世界类似 ---- 只要说“猫是哺乳动物”,猫的很多属性、行为就不言自明了 ---- 藏獒是一种狗 符合is-a关系的设计使用继承 ---- 继承是代码重用的一种方式 将子类共有的属性和行为放到父类中 h、代码分析 class Car { private int site = 4; //座位数 Car(){ System.out.println ("载客量是"+site+"人); } public void setSite(int site){ this.site = site; } void print(){ System.out.println ("载客量是"+site+"人); } } class Bus extends Car { Bus(int site){ setSite(site); } } public class BusTest{ public static void main(String[] args) { Bus bus = new Bus(20); bus.print(); } } i、小结 ---- 通过继承可以简化类的定义,实现代码的重用 ---- 子类继承父类的成员变量和成员方法,但不继承父类的构造方法 ---- java中只有单继承 ,没有像c++那样的多继承。多继承会引起混乱,使得继承链过于复 杂,系统难于维护。就像我们现实中,如果你有多个父母亲,那是一个多么混乱的世界啊。多继 承,就是为了实现代码的复用性,却引入了复杂性,使得系统类之间的关系混乱。 ---- java中的多继承,可以通过接口来实现 ---- 如果定义一个类时,没有调用extends,则它的父类是:java.lang.Object。 三、方法重写【课堂Demo同上】 1、在子类中可以根据需要对从基类中继承来的方法进行重写。 2、重写方法必须和被重写方法具有相同方法名称、参数列表和返回类型。 3、重写方法不能使用比被重写方法更严格的访问权限。(由于多态) 4、重写示例代码 public class TestOverride { public static void main(String[] args) { Animal animal = new Animal(); animal.shout(); Dog dog = new Dog(); dog.shout(); } } class Animal{ void shout(){ System.out.println("发出声音!"); } } class Dog extends Animal { void shout(){ System.out.println("旺旺旺!"); } } ? 5、小结: ---- 构造方法也会被重写吗? 不能被继承,因此不能重写 ---- 方法重写的规则 方法名相同 参数列表相同 返回值类型相同或者是其子类; 访问权限不能严于父类 ---- 方法重载与方法重写的区别   ? ---- super关键字来访问父类的成员 ---- super只能出现在子类的方法和构造方法中 ---- super调用构造方法时,只能是第一句 ---- super和this不能同时出现在构造方法中 ---- super不能访问父类的private成员 ---- super和this都不能再static方法中   四、抽象类、抽象方法 1、课堂Demo【重点掌握】 父类 Pet.java ?package netclass04.abstracts; /** * @Auther: Yu Panpan * @Date: 2022/1/12 - 01 - 12 - 14:36 * @Description: netclass04.abstracts * @version: 1.0 */ public abstract class Pet { private String name; private int age; public Pet(){ } public Pet(String name,int age){ this.name = name; this.age = age; } //抽象方法 public abstract void print(); public void show(){ System.out.println("Pet show... ..."); } } 子类 Dog.java package netclass04.abstracts; /** * @Auther: Yu Panpan * @Date: 2022/1/12 - 01 - 12 - 14:39 * @Description: netclass04.abstracts * @version: 1.0 */ public class Dog extends Pet{ private String gender; @Override public void print() { System.out.println("dog print... ..."); } } 测试类 PetTest.java package netclass04.abstracts; /** * @Auther: Yu Panpan * @Date: 2022/1/12 - 01 - 12 - 14:41 * @Description: netclass04.abstracts * @version: 1.0 */ /* * java中的对象是对现实世界的具象化,但是在现实世界中,某些类并不具备实例化的意义,因此可以定义为抽象类 * * 抽象类: * 1、创建抽象类的时候需要添加 abstract 的关键字 * 2、不能进行实例化,也就是不能new对象 * 3、抽象类中的某些方法需要子类进行更丰富的实现,父类实现没有意义,此时可以将抽象类 * 中的方法定义为抽象方法,没有具体的实现,只包含方法名称,返回值,参数列表,访问修饰符 * 4、使用abstract关键字修饰的方法叫做抽象方法,可以不写方法的实现 * 5、子类在继承抽象父类的时候,必须要将父类中的抽象方法进行实现或者将子类也定义为抽象类 * 6、有抽象方法的一定是抽象类,但是抽象类中不一定包含抽象方法 * */ public class PetTest { public static void main(String[] args) { Dog dog = new Dog(); dog.print(); // Pet pet = new Pet(); } } 五、final 1、课堂Demo【重点掌握】 FinalDemo.java package netclass04.abstracts; /** * @Auther: Yu Panpan * @Date: 2022/1/12 - 01 - 12 - 14:54 * @Description: netclass04.abstracts * @version: 1.0 */ /* * final的使用: * final可以修饰变量: * 表示变量的值不可变 * final可以修饰方法: * 表示方法不可以被重写 * final可以修饰类: * 表示类不可以被继承 * * */ public /*final*/ class FinalDemo { private String name; // public FinalDemo(){ // super(); // } public String getName() { return name; } public void setName(String name) { this.name = name; } public static final int num = 10; public final void show(){ System.out.println("FinalDemo... ..."); } public static void main(String[] args) { // FinalDemo fd = new FinalDemo(); // fd.num = 20; // FinalDemo.num = 20; // num = 20; // System.out.println(num); final FinalDemo fd = new FinalDemo(); fd.show(); // fd = new FinalDemo(); fd.setName("jason"); System.out.println(fd.getName()); } } FinlaSubClass.java package netclass04.abstracts; /** * @Auther: Yu Panpan * @Date: 2022/1/12 - 01 - 12 - 14:59 * @Description: netclass04.abstracts * @version: 1.0 */ public class FinalSubClass extends FinalDemo{ // @Override // public void show(){ // // } } ? 六、Object类 1、Object类是所有类的父类 一个类如果没有使用extends显性的继承另外一个类,那么这个类就继承自Object类。 2、源码解析(涉及到Object中常用的10个方法) getClass()、hashCode()、equals(Object)、clone()、toString()、notify()、notifyAll()、wait()、wait(long)、wait(long,int)   ? finalize()方法为过时的方法或者说是不推荐的方法,主要作用是标识在堆中的对象哪些是没有被引用的,方便JVM中的GC进行垃圾回收。 3、对象的比较—==和equals() a、==: ---- 比较两基本类型变量的值是否相等 ---- 比较两个引用类型的值即内存地址是否相等,即是否指向同一对象。 b、equals() : 两对象的内容是否一致 c、自定义类须重写equals(),否则其对象比较结果总是false。 通过阅读Object源码可知,equals()方法的实现是用==完成的
Object源码摘抄 public boolean equals(Object obj) { return (this == obj); }
4、Object课堂Demo【重点掌握】 ?package netclass04.abstracts; import java.util.Objects; /** * @Auther: Yu Panpan * @Date: 2022/1/12 - 01 - 12 - 15:14 * @Description: netclass04.abstracts * @version: 1.0 */ public class Teacher{ private String name; private int age; private double salary; public Teacher() { } public Teacher(String name, int age, double salary) { this.name = name; this.age = age; this.salary = salary; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } // @Override // public boolean equals(Object o){ // Teacher t =(Teacher) o; // return (this.name == t.name && this.age == t.age && this.salary == t.salary); // } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Teacher teacher = (Teacher) o; return age == teacher.age && Double.compare(teacher.salary, salary) == 0 && Objects.equals(name, teacher.name); } @Override public int hashCode() { return Objects.hash(name, age, salary); } @Override public String toString() { return "Teacher{" + "name='" + name + '\'' + ", age=" + age + ", salary=" + salary + '}'; } // @Override // public String toString(){ // return "name:" +this.name +" age:" +this.age +" salary:" + this.salary; // } public static void main(String[] args) { Teacher t1 = new Teacher("张飞",28,9000); // Teacher t2 = t1; Teacher t2 = new Teacher("张飞",28,9000); // System.out.println(t1 == t2);//true false // t2.setName("赵云"); System.out.println(t1.equals(t2));//true false System.out.println(t1);}} ? 七、总结 1、继承深化 a、父类方法的重写: ---- 方法名、形参列表相同。 ---- 返回值类型和异常类型,子类小于等于父类。 ---- 访问权限,子类大于等于父类 b、构造方法调用顺序: ---- 根据super的说明,构造方法第一句 总是:super(…)来调用父类对应的构造方法。 ---- 先向上追溯到Object,然后再依次向下执行类的初始化块和构造方法,直到当前子类为止。 八、作业 1、上机练习--课堂Demo【重点掌握】 某汽车租赁公司出租多种车辆,车型及租金情况如下:   ? 编写程序实现计算租赁价 案例分析: a、发现类 MotoVehical(机动车,抽象类)、Car、Bus b、发现类的属性 ---- MotoVehical:no(车牌号),brand(品牌) ---- Car:type(型号) ---- Bus:seatCount(座位数) c、发现类的方法 ---- MotoVehical:calcRent(int days) 抽象方法 ---- Car:Car(no,brand,type) 构造方法 ---- Bus:Car(no,brand,seatCount) 构造方法 d、优化设计,编写程序 机动车类:MotoVehical.java ?package netclass04.abstracts.homework; /** * @Auther: Yu Panpan * @Date: 2022/1/12 - 01 - 12 - 16:23 * @Description: netclass04.abstracts.homework * @version: 1.0 */ public abstract class MotoVehical { private String no; private String brand; public MotoVehical(){ } public MotoVehical(String no, String brand) { this.no = no; this.brand = brand; } public String getNo() { return no; } public void setNo(String no) { this.no = no; } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } //抽象方法(根据天数计算租金) public abstract int calcRent(int days); } 轿车类:Car.java package netclass04.abstracts.homework; /** * @Auther: Yu Panpan * @Date: 2022/1/12 - 01 - 12 - 16:25 * @Description: netclass04.abstracts.homework * @version: 1.0 */ public class Car extends MotoVehical { private String type; public Car(){ } public Car(String no,String brand,String type){ super(no,brand); this.type = type; } public String getType() { return type; } public void setType(String type) { this.type = type; } @Override public int calcRent(int days) { if(this.type.equals("0")){ return 600 * days; }else if(this.type.equals("1")){ return 500 * days; }else if(this.type.equals("2")){ return 300 * days; }else{ System.out.println("您输入的车型不存在!"); return 0; } } } 客车类:Bus.java package netclass04.abstracts.homework; /** * @Auther: Yu Panpan * @Date: 2022/1/12 - 01 - 12 - 16:28 * @Description: netclass04.abstracts.homework * @version: 1.0 */ public class Bus extends MotoVehical { private int seatCount; public Bus(){ } public Bus(String no,String brand,int seatCount){ super(no,brand); this.seatCount = seatCount; } public int getSeatCount() { return seatCount; } public void setSeatCount(int seatCount) { this.seatCount = seatCount; } @Override public int calcRent(int days) { if(this.seatCount > 16){ return 1500 * days; }else{ return 800 * days; } } } 测试类:MotoVehicalTest.java package netclass04.abstracts.homework; /** * @Auther: Yu Panpan * @Date: 2022/1/12 - 01 - 12 - 16:30 * @Description: netclass04.abstracts.homework * @version: 1.0 */ public class MotoVehicalTest { public static void main(String[] args) { // MotoVehical moto = new MotoVehical(); Car car = new Car("豫A 8888888","别克","0"); int total1 = car.calcRent(5); System.out.println("租金为:" +total1); Bus bus = new Bus("豫A 6666666","金杯",16); int total2 = bus.calcRent(5); System.out.println("租金为:" +total2); } } ? 2、上机练习 ?  

相关