【原】Java学习笔记019 - 面向对象
1 package cn.temptation; 2 3 public class Sample01 { 4 public static void main(String[] args) { 5 // 仔细想一想,Animal应该是一个抽象的概念,相对于Animal来说,狗才是具体的概念 6 // Animal的行为也应该算是一个抽象的行为 7 8 // Java中对于这些抽象的概念或是抽象的行为,提供了一个关键字 abstract 来进行修饰 9 10 // 关键字 abstract用在类上,类称为抽象类:abstract class 类名 11 // 关键字 abstract用在方法上,方法称为抽象方法:abstract 返回类型 方法名(参数列表) 12 13 // 抽象类不能进行实例化 14 // 原因:既然这个Animal类都是抽象的概念了,自然无法具体的创建出一个对象来,所以不能被实例化 15 // 语法错误:Cannot instantiate the type Animal 16 // Animal animal = new Animal(); 17 18 // 抽象类不能直接实例化使用,但是可以通过继承使用,使用多态写法 19 // Animal animal = new Dog(); 20 // 对于子类的成员方法,编译看赋值号左边,执行看赋值号右边 21 // animal.eat(); 22 } 23 } 24 25 //// 抽象类 26 //abstract class Animal { 27 // // 成员方法 28 // // 语法错误:Abstract methods do not specify a body 抽象方法没有方法体 29 //// public abstract void eat() { 30 //// System.out.println("动物会吃"); 31 //// } 32 // 33 // // 成员方法上使用了abstract,就变成了一个抽象成员方法 34 // // 没有方法体,意味着没有具体的实现,只是定义 35 // public abstract void eat(); 36 //} 37 // 38 //// 具体实现子类 39 //class Dog extends Animal { 40 // @Override 41 // public void eat() { 42 // System.out.println("狗会吃"); 43 // } 44 //}
1 package cn.temptation; 2 3 public class Sample02 { 4 public static void main(String[] args) { 5 // 抽象类 和 抽象成员方法的特点: 6 // 1、抽象类中可以有抽象的成员方法,也可以有非抽象的成员方法 7 // 2、只要类中有抽象的成员方法,该类就必须得是抽象类 8 // 3、抽象的成员方法没有方法体,只有小括号没有大括号,但是有分号作为结尾 9 // 4、抽象类不能被实例化,因为它被修饰为抽象的 10 // 5、抽象类可以有构造函数;虽然其构造函数不是用来做实例化的操作,但是可以提供给其子类创建对象时使用 11 // 6、抽象类的子类也可以是一个抽象类 12 // 7、不论抽象类中的成员方法是否为抽象的,只要类是抽象的,就不能实例化,也就不能使用对象名.成员方法来进行调用 13 } 14 } 15 16 // 抽象父类 17 abstract class Animal { 18 // 构造函数 19 public Animal() { 20 System.out.println("无参构造函数"); 21 } 22 23 // 成员方法 24 // 抽象的成员方法 25 public abstract void eat(); 26 27 // 非抽象的成员方法 28 public void sleep() { 29 System.out.println("动物能睡觉"); 30 } 31 } 32 33 // 抽象子类 34 abstract class Dog extends Animal { 35 36 } 37 38 // 抽象子类的具体实现的孙类 39 class ChineseDog extends Dog { 40 @Override 41 public void eat() { 42 System.out.println("中国狗会吃"); 43 } 44 } 45 46 // The abstract method test in type Demo can only be defined by an abstract class 47 //class Demo { 48 // // 抽象的成员方法 49 // public abstract void test(); 50 //}
1 package cn.temptation; 2 3 public class Sample03 { 4 public static void main(String[] args) { 5 // 抽象类成员的使用问题: 6 // 1、成员变量:可以是变量,也可以是自定义常量 7 // 2、构造函数:构造函数不是用来做实例化的,但是是提供给子类使用的 8 // 3、成员方法:可以是抽象的,也可以是非抽象的 9 // 抽象的成员方法:强制具体实现子类实现父类的抽象成员方法 10 // 非抽象的成员方法:子类可以重写、也可以不重写 11 12 Human human = new Man(); 13 System.out.println(human.i); 14 System.out.println(human.X); 15 } 16 } 17 18 // 抽象类 19 abstract class Human { 20 // 成员变量 21 public int i = 2; 22 public final int X = 3; 23 24 // 构造函数(无参) 25 public Human() { 26 System.out.println("无参构造函数"); 27 } 28 29 // 构造函数不能使用abstract修饰 30 // 语法错误:Illegal modifier for the constructor in type Human; only public, protected & private are permitted 31 // public abstract Human(); 32 33 // 构造函数(有参) 34 public Human(int i) { 35 this.i = i; 36 System.out.println(i); 37 } 38 39 // 成员方法 40 // 抽象的成员方法 41 public abstract void eat(); 42 43 // 非抽象的成员方法 44 public void sleep() { 45 System.out.println("人能睡觉"); 46 } 47 } 48 49 // 具体实现子类 50 class Man extends Human { 51 // 构造函数 52 public Man() { 53 super(99); 54 } 55 56 // 成员方法 57 // 不重写就会生成语法错误 58 // 语法错误:The type Man must implement the inherited abstract method Human.eat() Sample03.java /Day20170302_OOP/src/cn/temptation line 48 Java Problem 59 // 重写抽象的成员方法 60 public void eat() { 61 62 } 63 }
1 package cn.temptation; 2 3 public class Sample04 { 4 public static void main(String[] args) { 5 // 调用抽象类的静态成员变量 和 静态成员方法,使用类名.静态成员,无视该类是否为抽象类 6 // System.out.println(Phone.number); 7 // Phone.call(); 8 } 9 } 10 11 abstract class Phone { 12 // 静态成员变量 13 // static int number = 110; 14 15 // 静态成员方法 16 // static void call() { 17 // System.out.println("打电话"); 18 // } 19 20 // 抽象的成员方法 21 public abstract void method1(); 22 23 // private 和 abstract同时修饰,语法错误。 24 // 理解:private要求的是私有的,而abstract提出抽象的概念,需要后代去做实现,所以语义上是矛盾的 25 // 语法错误:The abstract method method2 in type Phone can only set a visibility modifier, one of public or protected 26 // private abstract void method2(); 27 28 // final 和 abstract同时修饰,语法错误。 29 // 理解:final要求的是子类不能重写父类的成员方法,而abstract提出抽象的概念,需要后代去做实现,所以语义上是矛盾的 30 // 语法错误:The abstract method method3 in type Phone can only set a visibility modifier, one of public or protected 31 // final abstract void method3(); 32 33 // static 和 abstract同时修饰,语法错误。 34 // 理解:static要求的是对象们(类的)的成员方法,而abstract提出抽象的概念(不是具体的),所以语义上是矛盾的 35 // 语法错误:The abstract method method4 in type Phone can only set a visibility modifier, one of public or protected 36 // static abstract void method4(); 37 }
1 package cn.temptation; 2 3 public class Sample05 { 4 public static void main(String[] args) { 5 // 需求:使用学过的知识点实现 6 // 东汉公司的员工都不睡觉 7 // 1、东汉公司的码农 吕布 是公司的员工,他写代码、打游戏,拿很少的薪水(1680) 8 // 2、东汉公司的经理 貂蝉 也是公司的员工,她做管理、听音乐,拿很多的薪水(20000) 9 10 Staff.companyName = "东汉"; 11 12 Staff staff1 = new Programmer("吕布", 1680); 13 System.out.println("姓名为:" + staff1.getName() + ",薪资为:" + staff1.getSalary() + ",公司名为:" + Staff.companyName); 14 staff1.nosleep(); 15 staff1.work(); 16 ((Programmer)staff1).playGame(); 17 18 Staff staff2 = new Manager(); 19 staff2.setName("貂蝉"); 20 staff2.setSalary(20000); 21 System.out.println("姓名为:" + staff2.getName() + ",薪资为:" + staff2.getSalary() + ",公司名为:" + Staff.companyName); 22 staff2.nosleep(); 23 staff2.work(); 24 ((Manager)staff2).listenMusic(); 25 } 26 } 27 28 /** 29 * 抽象类:员工类 30 */ 31 abstract class Staff { 32 // 成员变量 33 // 名字 34 private String name; 35 // 薪资 36 private int salary; 37 // 公司名 38 public static String companyName; 39 40 // 构造函数(无参) 41 public Staff() { 42 43 } 44 45 public Staff(String name, int salary) { 46 super(); 47 this.name = name; 48 this.salary = salary; 49 } 50 51 // 成员方法 52 public String getName() { 53 return name; 54 } 55 56 public void setName(String name) { 57 this.name = name; 58 } 59 60 public int getSalary() { 61 return salary; 62 } 63 64 public void setSalary(int salary) { 65 this.salary = salary; 66 } 67 68 // 自定义成员方法 69 /** 70 * 抽象成员方法:工作 71 * 等着具体实现子类去进行实现 72 */ 73 public abstract void work(); 74 75 /** 76 * 非抽象成员方法:不睡觉 77 * 不想被子类重写,可以使用final进行修饰 78 */ 79 public final void nosleep() { 80 System.out.println("不睡觉"); 81 } 82 } 83 84 /** 85 * 子类:程序员类 86 */ 87 class Programmer extends Staff { 88 // 成员变量 89 90 // 构造函数 91 public Programmer() { 92 super(); 93 } 94 95 public Programmer(String name, int salary) { 96 super(name, salary); 97 } 98 99 // 成员方法 100 @Override 101 public void work() { 102 System.out.println("写代码"); 103 } 104 105 public void playGame() { 106 System.out.println("打游戏"); 107 } 108 } 109 110 /** 111 * 子类:经理类 112 */ 113 class Manager extends Staff { 114 // 成员方法 115 @Override 116 public void work() { 117 System.out.println("做管理"); 118 } 119 120 public void listenMusic() { 121 System.out.println("听音乐"); 122 } 123 }
1 package cn.temptation; 2 3 public class Sample06 { 4 public static void main(String[] args) { 5 // Bird bird1 = new Eagle(); // 老鹰是一种鸟 6 // bird1.fly(); 7 // 8 // Bird bird2 = new Sparrow(); // 麻雀是一种鸟 9 // bird2.fly(); 10 // 11 // Bird bird3 = new Plane(); // 飞机是一种鸟 12 // bird3.fly(); 13 } 14 } 15 16 //// 抽象类:鸟类 17 //abstract class Bird { 18 // // 抽象方法:飞行 19 // public abstract void fly(); 20 //} 21 // 22 //// 具体子类:老鹰类 23 //class Eagle extends Bird { 24 // @Override 25 // public void fly() { 26 // System.out.println("老鹰的飞行"); 27 // } 28 //} 29 // 30 //// 具体子类:麻雀类 31 //class Sparrow extends Bird { 32 // @Override 33 // public void fly() { 34 // System.out.println("麻雀的飞行"); 35 // } 36 //} 37 // 38 //// 为了让飞机能飞行,强行让飞机从抽象父类鸟类进行继承,这样很别扭 39 //// 究其原因,因为子类继承父类,得到了父类的特征和行为(非私有的),这是一种先天的联系 40 //// 但是,在现实的世界中,除了描述先天上的联系,还有描述后天的关联 41 //// 这里的飞机会飞行,这不是先天上的天赋,而是后天具有的能力 42 //// 对于这些后天具备的能力,还去使用描述先天联系的继承去实现,就显得别扭了 43 // 44 //// 对于描述后天具备的能力,Java中提供了 接口(interface) 机制 45 // 46 //// 具体子类:飞机类 47 //class Plane extends Bird { 48 // @Override 49 // public void fly() { 50 // System.out.println("飞机的飞行"); 51 // } 52 //}
1 package cn.temptation; 2 3 public class Sample07 { 4 public static void main(String[] args) { 5 // 接口:描述事物具有的能力 6 7 // 格式:interface 接口名 { ... } 8 9 // 接口的实现形式: class 类名 implements 接口名 { .... } 10 11 // 注意: 12 // 1、接口不能实例化 13 // 2、如何使用接口? 14 // A:通过实现接口的类使用接口 15 // B:重写接口中定义的成员方法(类似抽象类的实现子类中的重写) 16 17 // 语法错误:Cannot instantiate the type Ability 18 // Ability ability = new Ability(); 19 20 // 常规写法(类的实例化) 21 // Plane plane = new Plane(); 22 // plane.fly(); 23 24 // 多态写法 25 // Ability plane = new Plane(); // 飞机具备能力 26 // plane.fly(); 27 28 // 关于多态及其重写使用的场合: 29 // 1、非抽象类继承后的多态(不常见) 30 // 2、抽象类继承后的多态(常见) 31 // 3、接口实现后的多态(常见) 32 } 33 } 34 35 //// 接口:能力接口 36 //interface Ability { 37 // // 接口中的方法没有方法体 38 // // 语法错误:Abstract methods do not specify a body 39 //// public void fly() { 40 //// 41 //// } 42 // 43 // // 接口中的方法必须是抽象的 44 // public abstract void fly(); 45 //} 46 // 47 //// 具体的飞机类 实现 能力接口 48 //class Plane implements Ability { 49 // @Override 50 // public void fly() { 51 // System.out.println("飞机 的飞行"); 52 // } 53 //}
1 package cn.temptation; 2 3 public class Sample08 { 4 public static void main(String[] args) { 5 // 接口的成员: 6 // 1、成员变量: 7 // 接口中的成员变量支持的修饰符:public static final 数据类型 成员变量名 8 // 通过对接口的字节码文件的反编译,发现接口中的成员变量的修饰符都是public static final修饰的,也就是这些成员变量都是接口的自定义常量 9 // 2、构造函数 10 // 接口不能有构造函数(接口不能实例化) 11 // 3、成员方法 12 // 接口中的方法必须是抽象的,不能是非抽象的 13 // 接口中的所有方法(都是抽象方法)必须要在实现类中进行实现 14 Test obj = new TestImpl(); 15 System.out.println(obj.i); 16 System.out.println(obj.j); 17 System.out.println(obj.k); 18 19 // 语法错误:The final field Test.i cannot be assigned 20 // obj.i = 99; 21 22 // 注意:"不能实例化的就一定没有构造函数"这种说法对不对? 答:不对,例如:抽象类 23 } 24 } 25 26 // 接口 27 interface Test { 28 // 成员变量 29 public int i = 2; 30 public final int j = 4; 31 public static final int k = 6; 32 // 语法错误:Illegal modifier for the interface field Test.x; only public, static & final are permitted 33 // private int x = 99; 34 35 // 构造函数 36 // 语法错误:Interfaces cannot have constructors 37 // public Test() { 38 // 39 // } 40 41 // 成员方法 42 // 非抽象的成员方法 43 // 语法错误:Abstract methods do not specify a body 44 // public void method() { 45 // 46 // } 47 48 // 抽象的成员方法 49 public abstract void method1(); 50 // 语法错误:Illegal modifier for the interface method method2; only public, abstract, default, static and strictfp are permitted 51 // private abstract void method2(); 52 } 53 54 // 接口的实现类 55 class TestImpl implements Test { 56 @Override 57 public void method1() { 58 59 } 60 }
1 package cn.temptation; 2 3 public class Sample09 { 4 public static void main(String[] args) { 5 // 1、类 和 类之间的关系 6 // 类和类之间可以是继承的关系(extends 关键字 inheritance) 7 // Java中的继承(针对类)是单继承,可以有继承链 8 9 // 2、类 和 接口之间的关系 10 // 类和接口之间是实现的关系(implements 关键字 implement) 11 // Java中的实现可以是单实现(具备某一种能力),也可以是多实现(具备多种能力) 12 // 注意:类与接口之间是实现的关系,没有继承的关系 13 14 // 3、接口 和 接口之间的关系 15 // 接口 和 接口之间可以是单继承,也可以是多继承 16 // 注意:接口不能实现另一个接口,因为接口定义的是规范,不是实现 17 18 // 面试题: 19 // Java语言是单继承、多实现的(×) 20 // 答:对于类,是单继承、多实现的;对于接口,是可以单继承,也可以多继承,但是不能实现其他接口或类 21 } 22 } 23 24 class GrandFather { 25 26 } 27 28 class Father extends GrandFather { 29 30 } 31 32 class Mother { 33 34 } 35 36 // 语法错误:Syntax error on token ",", . expected 37 //class Son extends Father, Mother { 38 // 语法错误:The type Eat cannot be the superclass of Son; a superclass must be a class 39 //class Son extends Eat { 40 class Son extends Father implements Eat, Sleep { 41 42 } 43 44 interface Eat { 45 46 } 47 48 interface Sleep { 49 50 } 51 52 // 接口可以多继承 53 //interface Lazy extends Eat, Sleep { 54 // 55 //} 56 57 // 语法错误:Syntax error on token "implements", extends expected 58 //interface Lazy implements Eat { 59 //interface Lazy implements Sleep { 60 //}
1 package cn.temptation; 2 3 public class Sample10 { 4 public static void main(String[] args) { 5 // 抽象类 和 接口的区别 6 /* 7 * 1、成员上的区别: 8 * 抽象类: 9 * A:成员变量:可以是变量,也可以是常量 10 * B:构造函数:有,但是不能实例化,只能供子类调用 11 * C:成员方法:可以有抽象的成员方法,也可以有非抽象的成员方法 12 * 13 * 接口: 14 * A:成员变量:都是常量(自定义常量) 15 * B:构造函数:没有构造函数 16 * C:成员方法:都是抽象的成员方法 17 * 18 * 2、关系上的区别: 19 * 类和类:单继承 20 * 类和接口:类可以是单实现接口,也可以是多实现接口 21 * 接口和接口:接口可以是单继承接口,也可以是多继承接口 22 * 23 * 3、设计意图上的区别: 24 * 抽象类:描述的是先天的天赋,有着抽象的概念、抽象的行为和具体实现子类是继承的关系,对于继承的具体实现子类来说描述了"is a(an)"的含义 25 * 抽象类中定义的成员是这些子类以及它们的后代共有的特征和行为(且不好具体描述) 26 * 接口:描述的是后天培养的、具备的能力,供类实现或是给其他接口继承,描述的是"like a(an)"或"as a(an)"的含义 27 * 接口中定义的是被实现的类需要扩展的功能 28 */ 29 30 // 【面向对象设计原则之一:"开闭原则"-----"对扩展开放,对修改封闭"】 31 // 换句话说,在面向对象的设计中,建议多使用接口,少使用继承 32 // 对于接口,应该理解其"规范性、强制性"的特点 33 } 34 } 35 36 // 接口:能力接口 37 interface Ability { 38 // 接口中的方法必须是抽象的 39 public abstract void fly(); 40 } 41 42 class Plane implements Ability { 43 // 实现了Ability接口,具备了接口定义的能力(方法) 44 @Override 45 public void fly() { 46 System.out.println("飞机能飞"); 47 } 48 }
1 package cn.temptation; 2 3 public class Sample11 { 4 public static void main(String[] args) { 5 // 需求:使用学过的知识(例如:抽象类、接口等)实现如下功能 6 // 1、吕布是个体育系的男学生,20岁,学习Java,会打篮球(因为是体育系的) 7 // 2、貂蝉是个音乐系的女学生,16岁,学习乐理,会弹棉花(因为是音乐系的) 8 9 Student student1 = new PE("吕布", 20, "男"); 10 student1.study("Java"); 11 ((PE)student1).doSport("篮球"); 12 13 Student student2 = new MusicalStudent("貂蝉", 16, "女"); 14 student2.study("乐理"); 15 ((MusicalStudent)student2).doEquipment("棉花"); 16 } 17 } 18 19 // 抽象类:学生类 20 abstract class Student { 21 // 成员变量 22 // 姓名 23 private String name; 24 // 年龄 25 private int age; 26 // 性别 27 private String gender; 28 // 系别 29 public static String dept = ""; 30 31 // 构造函数 32 public Student() { 33 super(); 34 } 35 36 public Student(String name, int age, String gender, String dept) { 37 super(); 38 this.name = name; 39 this.age = age; 40 this.gender = gender; 41 Student.dept = dept; 42 43 System.out.println("姓名为:" + this.name + ",年龄为:" + this.age + ",性别为:" + this.gender + ",系别为:" + Student.dept); 44 } 45 46 // 成员方法 47 public String getName() { 48 return name; 49 } 50 51 public void setName(String name) { 52 this.name = name; 53 } 54 55 public int getAge() { 56 return age; 57 } 58 59 public void setAge(int age) { 60 this.age = age; 61 } 62 63 public String getGender() { 64 return gender; 65 } 66 67 public void setGender(String gender) { 68 this.gender = gender; 69 } 70 71 // 自定义的成员方法 72 // 考虑到学生先天的天赋行为有学习,所以在抽象类中制作一个抽象方法study 73 public abstract void study(String course); 74 } 75 76 /** 77 * 具体实现子类:体育系学生 78 */ 79 class PE extends Student implements Sport { 80 // 成员变量 81 // 考虑到系别是子类的特征,所以定义为static 82 public static String dept = "体育系"; 83 84 // 构造函数 85 public PE() { 86 super(); 87 } 88 89 public PE(String name, int age, String gender) { 90 super(name, age, gender, PE.dept); 91 } 92 93 // 成员方法 94 @Override 95 public void study(String course) { 96 System.out.println("学习" + course); 97 } 98 99 @Override 100 public void doSport(String sportName) { 101 System.out.println("做" + sportName + "运动"); 102 } 103 } 104 105 /** 106 * 具体实现子类:音乐系学生 107 */ 108 class MusicalStudent extends Student implements Equipment { 109 // 成员变量 110 // 考虑到系别是子类的特征,所以定义为static 111 public static String dept = "音乐系"; 112 113 // 构造函数 114 public MusicalStudent() { 115 super(); 116 } 117 118 public MusicalStudent(String name, int age, String gender) { 119 super(name, age, gender, MusicalStudent.dept); 120 } 121 122 // 成员方法 123 @Override 124 public void study(String course) { 125 System.out.println("学习" + course); 126 } 127 128 @Override 129 public void doEquipment(String equipmentName) { 130 System.out.println("演奏" + equipmentName + "器械"); 131 } 132 } 133 134 // 运动能力接口 135 interface Sport { 136 public abstract void doSport(String sportName); 137 } 138 139 // 器械能力接口 140 interface Equipment { 141 public abstract void doEquipment(String equipmentName); 142 }