怎么去访问父亲的成员呢? java就提供了一个关键字:super super: super代表父类存储空间的标识(可以理解为父类对象) this和super的使用区别? A:成员变量 this.成员变量 本类的成员变量 super.成员变量 父类的成员变量 B:成员方法 this.成员方法() 本类的成员方法 super.成员方法()父类的成员方法 1.5 继承间的成员方法关系: A:方法名不同,非常简单 B:方法名相同 首先在子类中找 然后在父类中找 如果还是没有就报错。(不考虑父亲的父亲…) class Fu2{ public void show(){ System.out.println("fu2中的show方法"); } public void method(){ System.out.println("fu2的method方法"); } private void function(){ System.out.println("fu2的function方法"); } } class Zi2 extends Fu2{ public void show(){ System.out.println("zi2中的show方法"); } public void sleep(){ System.out.println("睡觉的方法"); } } public class ExtendsDemo4 { public static void main(String[] args) { //创建zi2的对象 Zi2 z = new Zi2(); z.sleep(); z.show(); z.method(); //z.fuction();//子类无法继承父类中私有的方法 } } 1.7 继承间构造方法的关系: 子类中所有的构造方法默认都会访问父类中空参数的构造方法(super()) 为什么呢? 因为子类会继承父类中的数据,可能还会使用父类的数据。 所以,子类初始化之前,一定要先完成父类数据的初始化。 每个子类的构造方法的第一行,有一条默认的语句: super(); 注意:仅仅是完成数据的初始化,创建对象目前必须用new申请空间。 假如父类没有无参构造方法,该怎么办呢? A:调用父类的其他构造方法。带参构造。 怎么访问呢? super(...) 注意: super(…)或者this(….)必须出现在第一条语句上。 因为如果可以放后面的话,就会对父类的数据进程多次初始化。所以,只能放在第一条语句上。 建议: 永远给出无参构造方法。 1.6 猫狗案例继承版 猫: 成员变量:type,name,age 构造方法:无参,带参 成员方法:getXxx()/setXxx() show() 狗: 成员变量:type,name,age 构造方法:无参,带参 成员方法:getXxx()/setXxx() show() 提取出动物类,完成代码,并测试。 DongWu -- Animal gou -- Dog mao -- Cat package com.edu_05; public class Animal { private String type; private int age; private String name; public Animal(){} public Animal(String name,String type,int age){ this.name = name; this.type = type; this.age = age; } public void setType(String type){ this.type = type; } public String getType(){ return type; } 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; } //吃饭的方法 public void eat(){ System.out.println("动物喜欢吃粮食"); } } package com.edu_05; public class Cat extends Animal{ public Cat(){} public Cat(String name,String type,int age){ setAge(age); setName(name); setType(type); } //猫喜欢吃鱼 /* public void eat(){ System.out.println("猫咪喜欢吃鱼"); } */ } package com.edu_05; public class Dog extends Animal{ //有参数和无参数的构造方法 public Dog(){} public Dog(String name,String type,int age){ setAge(age); setName(name); setType(type); } //狗喜欢吃肉 public void eat(){ System.out.println("狗喜欢吃肉"); } } package com.edu_05; public class Test { public static void main(String[] args) { //创建对象 Dog d = new Dog(); d.eat(); System.out.println("------------"); Cat c = new Cat("bob", "波斯猫", 2); c.eat(); System.out.println(c.getAge()+" "+c.getName()+" "+c.getType()); } } 1.7 水果案例继承版 苹果: 成员变量:品种,颜色,价格 构造方法:有参无参 成员方法:getXxx()/setXxx(); show() 橘子: 成员变量:品种,颜色,价格 构造方法:有参无参 成员方法:getXxx()/setXxx(); show() 提取水果类,完成代码,并测试 package com.edu_06; public class Fruit { private String type; private String color; public Fruit(){} public Fruit(String type,String color){} public void setType(String type){ this.type = type; } public String getType(){ return type; } public void setColor(String color){ this.color = color; } public String getColor(){ return color; } public void show(){ System.out.println(type+" "+color+" "); } } package com.edu_06; public class Apple extends Fruit{ //有参和无参构造 public Apple(){} public Apple(String type,String color){ setColor(color); setType(type); } } package com.edu_06; public class Test { public static void main(String[] args) { //创建Apple对象 Apple a = new Apple(); a.show(); System.out.println("-------------"); Apple a2 = new Apple("红富士", "红色"); a2.show(); System.out.println(a2.getColor()+" "+a2.getType()); } } 二:final关键字 在实际开发的时候,有些方法的内容一旦写定后,就不允许被改动。 即时是子类,也不允许。那么该怎么解决这个问题呢? java为了解决这样的问题就提供了一个关键字:final final: 最终的意思。它可以修饰类,方法,变量。 特点: 修饰方法,方法不能被重写。 修饰类,类不能被继承。 修饰变量,变量的值不能再改动。其实这个时候变量已经变成了常量。 常量: A:字面值常量 'a',12,"hello" B:自定义常量 就是把变量用final修饰。 定义一个常量。 final 数据类型 变量名; class Fu{//一个类如果被final修饰过后,就不能被继承 //写一个被final修饰的方法 public final void eat(){ System.out.println("fu的eat()"); } } class Zi extends Fu{ //尝试重写父类中的eat(),子类无发重写父类中被final修饰过的方法 /*public void eat(){ }*/ final int NUM = 20; //自定义一个常量,这个常量有多个单词组成 final int MAX_AGE = 30; final String URL = "WWW.BAIDU.COM"; } public class FinalDemo { public static void main(String[] args) { //创建Zi的对象,访问他的被final修饰过的成员变量num Zi z = new Zi(); //尝试改变被final修饰过的成员变量num //z.num = 30;//被final修饰过的变量不能被更改,此时他已经成了常量 System.out.println(z.NUM); } } 三:多态 3.1 多态:同一个对象,在不同时刻表现出来的不同状态。 举例: A:猫 猫是猫 猫是动物 B:水 水(液态) 冰(固态) 水蒸气(气态) 多态的前提: A:有继承关系 B:有方法重写(不是必要条件,但是只有有了方法重写多态才有意义) C:有父类引用指向子类对象 Fu f = new Fu(); 左边:Fu类型的引用 右边:Fu类型的对象 Zi z = new Zi(); Fu f = new Zi(); 3.2 成员访问特点 A:成员变量 编译看左边,运行看左边 B:构造方法 子类构造默认访问父类的无参构造 C:成员方法(重点理解) 编译看左边,运行看右边 为什么变量和方法不一样呢? 方法重写。 D:静态成员方法 编译看左边,运行看左边 因为静态的内容是和类相关的,与对象无关。 练习: 看程序写结果(先判断有没有问题,如果没有,写出结果) class Fu { public void show() { System.out.println("fu show"); } } class Zi extends Fu { public void show() { System.out.println("zi show"); } public void method() { System.out.println("zi method"); } } class DuoTaiTest { public static void main(String[] args) { Fu f = new Zi(); f.method(); f.show(); } } 代码示例: class Fu{ //创建一个成员变量 int num = 20; public void show(){ System.out.println("fu的show()"); } public static void method(){ System.out.println("fu的method()"); } } class Zi extends Fu{//1.存在继承关系 int num = 30; public void show(){//2.存在方法重写 System.out.println("zi的show"); } public static void method(){ System.out.println("zi的method()"); } } public class DuoTaiDemo { public static void main(String[] args) { //3.父类引用指向子类对象 Fu f = new Zi(); System.out.println(f.num); //多态的情况下:成员变量的访问特点是,编译看左边,运行看左边 System.out.println("---------------------------"); f.show(); //多态的情况下:成员方法的访问特点:编译看左边,运行看右边 System.out.println("---------------------------"); f.method(); //多态情况下静态成员方法的访问特点:编译看左边,运行看左边 } } 练习:(猫狗案例演示) 如何使用子类特有功能 A:创建子类对象 B:把父类引用转为子类对象 向上转型 从子到父 父类引用指向子类对象 向下转型 从父到子 父类引用转为子类对象 package com.edu_09; public class Animal { private String type; private int age; private String name; public Animal(){} public Animal(String name,String type,int age){ this.name = name; this.type = type; 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 getAage(){ return age; } public void setType(String type){ this.type = type; } public String getType(){ return type; } //吃的方法 public void eat(){ System.out.println("动物喜欢吃饭"); } } package com.edu_09; public class Cat extends Animal{ public Cat(){} public Cat(String name,String type,int age){ setAge(age); setName(name); setType(type); } //猫喜欢池鱼 public void eat(){ System.out.println("猫喜欢吃鱼"); } //猫有一个特有的功能,猫会捉老鼠 public void catchMouce(){ System.out.println("猫有一个捉老鼠的特有技能"); } } package com.edu_09; public class Dog extends Animal{ public Dog(){} public Dog(String name,int age,String type){ setAge(age); setName(name); setType(type); } //狗有一个特有技能会看门 public void lookDoor(){ System.out.println("狗会看门"); } } public class Test { public static void main(String[] args) { //使用多态的方式创建一个Cat对象 Animal a = new Cat(); a.eat(); //a.catchMouce(); //需求:就像在这里调用猫中特有功能,捉老鼠 //方式1:创建Cat对象,使用Cat类型去接受 Cat c = new Cat(); c.catchMouce(); System.out.println("------------"); //方式2:向下转型,将父类引用转换成子类对象 Cat c2 = (Cat)a; c2.catchMouce(); System.out.println("--------------"); //将a这个引用转换成Dog对象??? //Dog d = (Dog)a; //java.lang.ClassCastException:类型转换异常 //d.eat(); //d.lookDoor(); System.out.println("----------------"); Animal a2 = new Dog(); a2.eat(); //a2.lookDoor(); Dog d = (Dog)a2; d.lookDoor(); } } 四:抽象类 4.1 抽象类特点: A:抽象类和抽象方法必须用abstract关键字修饰 B:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类 C:抽象类不能实例化 那么,如果实例化并使用呢? 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。 D:抽象类的子类 要么是抽象类 要么重写抽象类中的所有抽象方法 抽象类的作用: 强制要求子类必须要重写某些方法。 abstract class Animal{ //抽象类中不一定有抽象方法 public void sleep(){ System.out.println("动物都喜欢睡大觉"); } //定义一个抽象方法,1.使用abstract进行修饰 2,抽象方法没有方法体,因为抽象根本就不是一个具体的方法 //3.如果一个类中有抽象方法,这个类一定是抽象类 4.抽象方法没有具体的实现,需要让他的具体子类做具体的实现 public abstract void eat(); } class Dog extends Animal{ @Override public void eat() { System.out.println("狗喜欢吃肉"); } } class Cat extends Animal{ @Override public void eat() { System.out.println("猫喜欢吃鱼"); } } //定义一个抽象类继承Animal这个类,如果一个抽象类继承另一个抽象类,不需要重写父类中的抽象方法 //abstract class Person extends Animal{} public class AbstractDemo { public static void main(String[] args) { //创建狗的对象 Dog d = new Dog(); d.eat(); System.out.println("----------"); //使用多态的方式创建对象,并调用eat()方法 //此时使用的多态的方式是:抽象类多态 /** * 多态的分类: * 1.普通类多态 * 2.抽象类多态 * 前两种全部是父类引用指向子类对象 * 3.接口多态 * 父接口引用指向接口实现类对象 */ Animal a = new Dog(); a.eat(); } } 4.2 抽象类 -- 特点 -- 成员特点 -- 案例 类的组成: 成员变量: 构造方法: 成员方法: 抽象类的成员: 成员变量:可以是变量,也可以是常量。 构造方法:有构造方法 不能实例化,构造方法有什么用呢? 用于子类访问父类数据的初始化。 成员方法:既可以是抽象的,也可以是非抽象的。 abstract class Animal2{ //成员变量:可以是变量,也可以是常量。 int num = 10;//变量 final int num2 = 20; //抽象类有构造方法吗??? //既然我们刚才说过我们的抽象类不能被实例化,为什么抽象类还可以具有构造方法呢? //这里的构造方法是为了初始化我们的父类数据,并不是用来做一个对象的实例化的 public Animal2(){} //成员方法:可以是普通成员方法,也可以是抽象方法, //一个类如果具有抽象方法这个类一定是抽象类 } 4.3 抽象类练习 以后我们在写代码的时候,有这样的分析过程。 分析: 从具体到抽象。 实现: 从抽象到具体。 使用: 使用具体的类。 猫: 成员变量: name,age,type 构造方法: 有参无参 成员方法; getXxx()/setXxx() eat(),catchMouse() 狗: 成员变量: name,age,type 构造方法: 有参无参 成员方法; getXxx()/setXxx() eat(),lookDoor() 发现有共性的内容,所以我们就提取出一个父类出来: 动物:抽象类 成员变量: name,age,type 构造方法: 有参无参 成员方法; getXxx()/setXxx() eat()---抽象的 猫: 继承自动物 构造方法: 狗: 继承自动物 构造方法: package com.edu_11; public abstract class Animal { private String type; private String name; public Animal(){} public Animal(String type,String name){ this.name = name; this.type = type; } public void setType(String type){ this.type = type; } public String getType(){ return type; } public void setName(String name){ this.name = name; } public String getName(){ return name; } //吃饭的抽象方法 public abstract void eat(); } package com.edu_11; public class Cat extends Animal{ public Cat(){} public Cat(String name,String type){ setName(name); setType(type); } @Override public void eat() { System.out.println("猫爱吃鱼"); } //猫会捉老鼠 public void catchMouse(){ System.out.println("猫会逮老鼠"); } } package com.edu_11; public class Dog extends Animal{ public Dog(){} public Dog(String name,String type){ setName(name); setType(type); } @Override public void eat() { System.out.println("狗爱吃肉"); } //狗特有的看门方法 public void lookDoor(){ System.out.println("狗会看门"); } } package com.edu_11; public class Test { public static void main(String[] args) { //利用多态的方式创建一个狗的对象 Animal a = new Dog(); a.eat(); Dog d = (Dog)a; d.lookDoor(); System.out.println("--------------"); //使用猫的有参构造创建一个对象 Animal a2 = new Cat("bob", "加菲猫"); a2.eat(); System.out.println(a2.getName()+" "+a2.getType()); } } 多态: 具体类多态 class Fu {} class Zi extends Fu {} 抽象类多态 abstract class Fu {} class Zi extends Fu {} 接口多态 多态的前提: 继承 方法重写 因为抽象类中的方法是抽象方法。 父类引用指向子类对象 作业分析(上课做简单分析,下课代码自己实现): 老师案例 具体事物:基础班老师,就业班老师 共性:姓名,年龄,讲课。 自己分析自己写 基础班老师: 成员变量:姓名,年龄 构造方法:无参,带参 成员方法:getXxx()/setXxx() show() 讲课() 就业班老师: 成员变量:姓名,年龄 构造方法:无参,带参 成员方法:getXxx()/setXxx() show() 讲课() 老师:抽象类 成员变量:姓名,年龄 构造方法:无参,带参 成员方法:getXxx()/setXxx() show() 讲课() 抽象方法 基础班老师: 构造方法:无参,带参 成员方法:讲课() 抽象方法 就业班老师: 构造方法:无参,带参 成员方法:讲课() 抽象方法 package com.edu10; public abstract class Person { private String name; private int age; public Person(){} public Person(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; } public abstract void show(); } package com.edu10; public class BasicTeacher extends Person{ public BasicTeacher (){} public BasicTeacher(String name,int age){ setAge(age); setName(name); } public void show(){ System.out.println("老师讲的是基础课"); } } package com.edu10; public class JobTeacher extends Person{ public JobTeacher(){} public JobTeacher(String name,int age){ setAge(age); setName(name); } public void show(){ System.out.println("老师是就业班老师"); } } package com.edu10; public class Test { public static void main(String[] args) { Person p=new BasicTeacher(); p.show(); Person p1=new JobTeacher("马老师",20); p1.show(); System.out.println(p1.getName()+" "+p1.getAge()); } } 五:接口 5.1 认识接口:不是我们现实生活中的usb接口等等实物的接口,类实现接口代表着这个类自身功能的一种扩展, 所以接口代表着一种扩展的能力 5.2 接口的特点: A:定义接口要用关键字interface表示 格式:interface 接口名 {} B:类实现接口用implements表示 格式:class 类名 implements 接口名 {} C:接口不能实例化 那么,接口如何实例化呢? 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,接口多态。 D:接口的实现类 要么是抽象类 要么重写接口中的所有抽象方法 多态的前提: A:有继承或者实现关系 B:有方法重写 C:有父类引用或者父接口引用指向子类或者实现类对象 多态分类: A:具体类多态 B:抽象类多态 C:接口多态 interface inter{ //接口中可以定义那些东西呢? //1.在接口中定义一些变量 //接口中所有的变量都会默认被final修饰,所以我们的接口中说白了只能定义常量,不能定义变量 //接口中的成员变量不仅被final默认修饰,还被static默认修饰 //我们接口中的变量全部是静态常量 public static final int num = 20; //2.接口中能否定义一个构造方法呢?? //接口中不能存在构造方法 //public inter(){} //3.接口中可以存在普通的成员方法吗? //接口中的所有方法都是抽象方法 public abstract void show(); } //定义一个类实现这个接口 class InterImpl implements inter{ @Override public void show() { System.out.println("来自接口中扩展的抽象方法"); } } //定义一个抽象类,让这个抽象类实现接口,此时这个抽象类不需要重写接口中的抽象方法 abstract class AbstractInterImpl implements inter{} public class InterfaceDemo { public static void main(String[] args) { //利用多态的方式将接口进行实例化 inter i = new InterImpl(); //试图更改成员变量的值 //i.num = 30;//接口中所有的变量都会默认被final修饰,所以我们的接口中说白了只能定义常量,不能定义变量 //System.out.println(i.num); System.out.println(inter.num); } } 5.3 接口的成员特点: A:成员变量 只能是常量。 默认修饰符:public static final B:构造方法 没有构造方法 C:成员方法 只能是抽象方法。 默认修饰符:public abstract 5.4 类与类: 继承关系。只能单继承,可以多层(重)继承。 类与接口: 实现关系。可以单实现,也可以多实现。 还可以在继承一个类的同时实现多个接口。 接口与接口: 继承关系。可以单继承,也可以多继承。 5.5 接口和抽象类的关系最后分析: 抽象类和接口的区别 A:成员区别 抽象类: 成员变量:可以是变量,也可以是常量 构造方法:有构造方法 成员方法:可以是抽象方法,也可以是非抽象方法 接口: 成员变量:只能是常量。默认修饰符 public static final 成员方法:只能是抽象方法。默认修饰符 public abstract B:关系区别 类与类: 继承关系。只能单继承,可以多层(重)继承。 类与接口: 实现关系。可以单实现,也可以多实现。 还可以在继承一个类的同时实现多个接口。 接口与接口: 继承关系。可以单继承,也可以多继承。 C:设计理念区别 抽象类被继承体现的是:"is a"的关系。抽象类定义的是共性功能。 接口被实现体现的是:"like a"的关系。接口定义的是扩展功能。 interface Inter1{} interface Inter2{} interface Inter3 extends Inter2,Inter1{} //创建一个类实现一个接口,或者多个接口 class InterImpl3 implements Inter1,Inter2{} //一个类还可以在继承一个类的同时实现多个接口 class InterImpl4 extends InterImpl3 implements Inter3{} 5.6 继承,抽象类,接口代码综合演练 分析:从具体到抽象 实现:从抽象到具体 使用:使用具体类 猫狗案例,加入跳高的额外功能 猫: 成员变量: name,age 构造方法: 无参,带参 成员方法: getXxx()/setXxx() show() catchMouse() eat() 跳高猫:继承自猫 成员方法: 跳高 狗: 成员变量: name,age 构造方法: 无参,带参 成员方法: getXxx()/setXxx() show() lookDoor() eat() 跳高狗:继承自狗 成员方法: 跳高 无论猫还是狗,都是动物,所以我们提取出一个动物类: 跳高接口: 跳高 动物类:抽象类 成员变量: name,age 构造方法: 无参,带参 成员方法: getXxx()/setXxx() show(){} eat(); 抽象方法 猫:继承自动物 构造方法: 无参,带参 成员方法: catchMouse() eat() 跳高猫:继承自猫,实现跳高接口 构造方法: 无参,带参 成员方法: 跳高 狗:继承自动物 构造方法: 无参,带参 成员方法: lookDoor() eat() 跳高狗:继承自狗,实现跳高接口 构造方法: 无参,带参 成员方法: 跳高 package com.edu_13; public abstract class Animal { //私有化成员变量 private String name; private int age; //有参无参构造 public Animal(){} public Animal(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; } //吃的抽象方法 public abstract void eat(); } package com.edu_13; public class Cat extends Animal{ public Cat(){} public Cat(String name,int age){ setAge(age); setName(name); } @Override public void eat() { System.out.println("猫爱吃鱼"); } //所有的猫都会逮老鼠 public void catchMouse(){ System.out.println("猫会逮老鼠"); } } package com.edu_13; public class Dog extends Animal{ //有参无参构造 public Dog(){} public Dog(String name,int age){ setAge(age); setName(name); } @Override public void eat() { System.out.println("狗吃骨头"); } //所有的狗都会看门 public void lookDoor(){ System.out.println("狗会看家"); } } package com.edu_13; public interface Inter { public abstract void jump(); } package com.edu_13; public class JumpCat extends Cat implements Inter{ public JumpCat(){} public JumpCat(String name,int age){ setAge(age); setName(name); } @Override public void jump() { System.out.println("经过多年的刻苦训练,终于练成了跳高技能"); } } package com.edu_13; public class JumpDog extends Dog implements Inter{ public JumpDog(){} public JumpDog(String name,int age){ setAge(age); setName(name); } @Override public void jump() { System.out.println("这条狗不简单呐,居然会跳高"); } } package com.edu_13; public class Test { public static void main(String[] args) { //多态的方式创建一个普通狗 Animal a = new Dog(); a.eat(); Dog d = (Dog)a; d.lookDoor(); System.out.println("------------------"); //创建一个跳高狗 JumpDog jd = new JumpDog(); jd.eat(); jd.lookDoor(); jd.jump(); } }