目录
复习重写
方法重写的类型的返回值必须严格相同:
抽象类
接口
代码:鼠标和键盘插入
兔子狗鸭子
关于接口的命名规范
Object类
目录
复习重写
方法重写的类型的返回值必须严格相同:
抽象类
接口
代码:鼠标和键盘插入
兔子狗鸭子
复习重写 |
package abstract_class; class Person { //父类 parent class public void fun(){ this.test(); } private void test(){ // The test method is private,Subclasses don't even know test exists. //so ,unable to rewrite. //private method only visible inside the current class. System.out.println("Person test method"); } } class Student extends Person{//子类 subclasses public void test(){ System.out.println("test method of student class "); } } public class Test{ public static void main(String[] args) { new Student().fun(); //The fun method only exists in parent class. } }package abstract_class; class Person { //父类 parent class public void fun(){ this.test(); } void test(){// After the elimination of private. System.out.println("Person test method"); } } class Student extends Person{//子类 subclasses //The subclass is overridden 此时子类被重写了 public void test(){ System.out.println("test method of student class "); } } public class Test{ public static void main(String[] args) { new Student().fun(); //The fun method only exists in parent class. } }code output "test method of student class "!!
子类和父类有不同的标记符号:
子类向上,父类向下;
方法重写的类型的返回值必须严格相同: |
毫无相关的 两种类型不能作为方法重写的返回值,比如受父类中的是int而子类中的是boolean,这就不可以返回,不算方法重写,会报成不兼容。
这时子类使用student作为返回值,父类使用Person作为返回值是可以的,因为这个student本来就是Person, student is a person。
package abstract_class;
class Person { //父类 parent class
public void fun(){
this.test();
}
Person test(){
System.out.println("Person test method");
return new Person();
}
}
class Student extends Person{//子类 subclasses
public Student test(){
System.out.println("test method of student class ");
return new Student();
}
}
public class Test{
public static void main(String[] args) {
new Student().fun();
//The fun method only exists in parent class.
}
}
如果反过来父类中是返回Student,子类中返回person 呢?
会报错:“attempting to use incompatible return type” 尝试使用不兼容的类型。
原因这时是向下转型,而不是向上转型,person is not a student,
package abstract_class;
class Person { //父类 parent class
public void fun(){
this.test();
}
Student test(){
System.out.println("Person test method");
return new Student();
}
}
class Student extends Person{//子类 subclasses
public Person test(){
System.out.println("test method of student class ");
return new Person();
}
}
public class Test{
public static void main(String[] args) {
new Student().fun();
//The fun method only exists in parent class.
}
}
一般情况下,重写方法的返回值类型不一定和父类相同,但是建议写成相同。
抽象类 |
抽象类只是比普通类多了一些抽象的方法,可以是0个或者n个。
抽象方法所在的类必须是抽象类,子类若继承了抽象类,必须复习所有的抽象方法(但是子类必须是不同类)。
抽象方法是使用abstract关键字声明,没有函数实现的方法。
java中定义抽象类或者抽象方法使用abstract关键字;
抽象方法的实现要在子类中去实现。
| 1只要使用抽象类必须用abstract声明为抽象类 此时的print只有方法的声明,没有方法体。所谓的方法体就是{} | 没有方法体的方法不一定就是抽象方法。 |
| 本地方法 | native表示本地的,这个方法不是抽象方法,具体实现由C++写好的方法完成。 |
| 2若一个类使用abstract声明为抽象类,无法直接通过该类实例化对象,哪怕该类中一个抽象方法都没有。当一个类是抽象类,不管有没有抽象方法,这个类本身就是一个抽象的概念,没法具体到某个特定实例。 | 抽象类不能自己实例化对象,只能通过子类向上转型转为抽象父类的引用。 Sharp sharp =new Sharp(); // false 人类是一个抽象的概念 Person person= new Person(); // false Person person=new China(); // true |
| 3子类继承了抽象类就必须强制要求重写所有的抽象方法(子类是个普通类),一个子类只能extends一个抽象类 | 类“C”必须声明为抽象,或者实现抽象方法“printB()” |
| 如果B中没有重写A,那么普通类C要实现两次 | package Sharp;
public class code1 {
abstract class A{
abstract void printA();
}
//B 是一个抽象类,可以选择性的重写父类中的抽象方法
abstract class B extends A{
//这个pintA B没有重写
abstract void printB();
}
//C是普通类,必须重写B中的所有抽象方法
class C extends B{
@Override
void printA() {
}
@Override
void printB() {
}
}
} |
| 如果B重写了A | package Sharp;
public class code1 {
abstract class A{
abstract void printA();
}
//B 是一个抽象类,可以选择性的重写父类中的抽象方法
abstract class B extends A{
abstract void printB();
//如果我在B中重写了A,C就不需要重写两次了
@Override
void printA() {
}
}
//C是普通类,必须重写B中的所有抽象方法
class C extends B{
@Override
void printB() {
}
}} |
| 4.抽象类虽然没法直接实例化对象,但是可以存在构造方法,子类在实例化对象的时候仍遵从继承的原则。先调用父类的构造方法,而后调用子类的构造方法。 | package Sharp;
abstract class BaseTest{
public BaseTest(){
this.print();
}
abstract void print();
}
public class Fun extends BaseTest{
private int num=10;
@Override
void print() {
System.out.println("num="+num);
}
public static void main(String[] args) {
new Fun();
}
}
先调用父类,然后this.print()调用被子类重写的方法,此时num==0; |
到底啥时候会用到抽象类,稍微复杂一点,先阶段主要掌握接口类的定义与使用。
若一个需求既可以使用抽象类也可以使用接口,优先使用接口 ,因为抽象类依然是单继承局限。
接口 |
| 抽象类虽然没法直接实例化对象,但是子类仍然满足 is a 原则,子类和抽象父类之间仍然是一个强的继承树关系,Person 对于China 和Sharp 对于Cycle, China 只能继承Person, Cycle 只能继承 Sharp,而接口是一个混合的概念,他不是一个垂直的方向。接口的使用一般表示两种, |
| 1.接口表示具备某种能力或者行为,子类在实现接口时不是 is a 关系,而是具备这种行为能力。 比如 游泳 ,Person 满足游泳接口, Dog也能满足游泳的接口,他是一个混合的实现,Duck 也能满足游泳接口,此时游泳接口就是一个表示游泳能力或者行为。 |
| 2.接口表示一种规范,比如“USB”接口,“5G标准”。 |
接口中只有全局常量和抽象方法,更加存粹的抽象概念,其他东西都没有。
接口使用关键字-interface声明接口,子类使用implement实现接口;
1.USB接口
USB接口表示一种规范,那么显示生活中哪些类使我们接口的子类,鼠标,键盘这种外设都是。
子类使用implements实现接口,必须重写所有的抽象方法。
电脑这个类不属于USB接口的子类,所有带USB线插入到电脑的设备都应该满足USB规范,电脑叫做USB规范的使用者。
其实鼠标和键盘我们都需要各有一个接口,所以这个例子不太好。
代码:鼠标和键盘插入
package usb;
public interface USB {
// 插入
public abstract void plugIn();
//工作
public abstract void work();
}
package usb;
public class Mouse implements USB{
@Override
public void plugIn() {
System.out.println("安装鼠标驱动");
}
@Override
public void work() {
System.out.println("鼠标开始工作");
}
}
package usb;
public class KeyBoard implements USB{
@Override
public void plugIn() {
System.out.println("安装键盘驱动中");
}
@Override
public void work() {
System.out.println("键盘正常工作");
}
}
package usb;
public class Computer {
public static void main(String[] args) {
Computer computer=new Computer();
Mouse mouse =new Mouse();
//调用fun方法把mouse传入,插入一个鼠标
computer.fun(mouse);
KeyBoard keyBoard=new KeyBoard();
computer.fun(keyBoard);
}
public void fun(USB usb){
usb.plugIn();
usb.work();
}
}
安装鼠标驱动
鼠标开始工作
安装键盘驱动中
键盘正常工作
假如现在这可接口要插入Camera,电脑的fun方法不用变,只要写一个子类,然后创建对象,引用传入就行了,这也是多态。
开闭原则,所有设计模式的核心思想:程序应该的拓展开放,对修改关闭。方便扩展,不能影响已经写好的程序。
接口表现能力!
接口允许多实现,一个类可以具备多种能力 ,同时实现多父接口,若实现多个父接口,子类普通类,需要复写所有抽象方法。
一个类既需要继承一个父类又需要实现多个接口时:
类名 extends 父类 implements 接口1,接口2...{}
兔子狗鸭子
package animal;
public interface ISWim {
public abstract void swim();
}
package animal;
public interface IRun {
public abstract void run();
}
package animal;
public interface IFly {
public abstract void fly();
}
package animal;
//兔子只会跑不会游泳
public class Rabbit implements IRun{
@Override
public void run() {
System.out.println("兔子再跑~~");
}
}
package animal;
//Dog会跑也会游泳
public class Dog implements IRun,ISWim{
@Override
public void run() {
System.out.println("狗在跑~~~~");
}
@Override
public void swim() {
System.out.println("狗在游泳~~~~");
}
}
package animal;
//鸭子会跑回游会飞
public class Duck implements IRun,IFly,ISWim {
@Override
public void fly() {
System.out.println("鸭子在飞");
}
@Override
public void run() {
System.out.println("鸭子在跑");
}
@Override
public void swim() {
System.out.println("鸭子在游泳");
}
}
package animal;
public class Test {
public static void main(String[] args) {
//接口也不能直接实例化对象,需要向上转型
IRun run = new Rabbit();
IRun run1 = new Dog();
IRun run2 = new Duck();
ISWim swim = new Dog();
ISWim swim1 = new Duck();
IFly fly = new Duck();
run.run();
run1.run();
run2.run();
swim.swim();
swim1.swim();
fly.fly();
}
}
兔子再跑~~
狗在跑~~~~
鸭子在跑
狗在游泳~~~~
鸭子在游泳
鸭子在飞
| 由于接口中只会有全局常量和抽象方法,因此接口中 public abstract=>抽象方法 static final=>常量 全都可以省略!!! |
package animal;
public class Test {
public static void main(String[] args) {
//接口也不能直接实例化对象,需要向上转型
IRun run = new Rabbit();
IRun run1 = new Dog();
IRun run2 = new Duck();
ISWim swim = new Dog();
ISWim swim1 = new Duck();
IFly fly = new Duck();
run.run();
run1.run();
run2.run();
swim.swim();
swim1.swim();
fly.fly();
}
} |
| 兔子再跑~~ 狗在跑~~~~ 鸭子在跑 狗在游泳~~~~ 鸭子在游泳 全局常量 鸭子在飞 |
| 在定义抽象方法时,abstract和final不能同时出现,抽象方法必须 重写,final修饰后无法重写。 在定义抽象类时,也不可以,抽象类必须有子类,final修饰没有子类。 |
关于接口的命名规范 | 命名接口使用 I 开头,IRun,ISwim |
| 子类实现一个接口时 | 命名以相应的接口开头,以impl结尾, eg:如果是IRun的子类,以IRunimpl结尾,这个命名不是强制要求。 |
| 如果子类实现多个父接口不需要使用此规范来命名 | 比如Duck即会游泳有会跑又会飞就不需要使用固定的结尾 |
Object类 |
| 全名称: 包名.类名 java.lang.Object |
| 1.Object类是java中所有类默认的父类,无需使用extends来定义,class声明的类都有一个父类,Object类。 因为object类是所有类的子类,使用Object引用来接收所有类型,参数最高统一化。 Object obj1=new Person(); Object obj2=new String(); Object obj3=new Dog(); 都可以通过向上转型变成object,所有类型都可以,这叫参数的最高统一化。 假如说有一个参数实object类型的,void fun(Object obj){},说明他可以接受所有的类型。 |
| 2.Object是所有类的父类,那么子类可以继承父类的所有方法! 之所以System.out.prientln(任意的引用类型)-->默认都调用toString()方法,是因为Object类存在toString方法。 这就是为什么sout中传入什么类型的对象都能够打印的原因。 还有,方法能不能重写看的是前面的引用有没有这个属性,如果有就调用子类重写后的代码: |
| 3.java中引用数据类型之间的相等比较使用equals方法! 不能使用“==”比较的是地址; Object类存在equals方法! |



