java第四节 类的继承/抽象/接口/多态性

时间:2022-11-23 14:30:22
/*
类的继承
类的继承可以简化类的定义
java只支持单继承,不允许多重继承
可以有多层继承,即一个类可以继承其一个类的子类,如类B继承了类A,类C又可以继承类B
那么类C也间接继承了类A 子类继承父类所有的成员变量和成员方法,但不继承父类的构造方法,
在子类的构造方法中可使用语句super(参数列表)
调用父类的构造方法 如果子类的构造方法中没有显式地调用父类构造方法,也没用使用this关键字调用重载的其它构造方法,则在产生子类的实例对象时
系统默认调用父类无参数的构造方法 子类对象的实例化过程 1 分配成员变量的存储空间并进行默认的初始化,就是用new关键字产生对象后
对类中的成员变量按第三章的表3.1的对应关系对对象中的成员变量进行初始化赋值 2 绑定构造方法参数,就是new Person(实际参数列表)中所传递进的参数赋值给构造方中的形式参数变量 3 如果有this()调用,则调用相应的重载构造方法(被调用的重载构造方法又从步骤2开始执行这些流程)
被调用的重载构造方法的执行流程结束后,回到当前构造方法,当前构造方法直接跳转到步聚6执行 4 显示或隐式追溯调用父类的构造方法(一直到Ojbect类为止,Object是所有java类的最顶层父类)
在本音后面部分有详细讲解,父类的构造方法又从步骤2开始对父类执行这些流程,父类的构造方法的执行流程结束后,回到当前构造方法,当前构造方法继承往下执行 5 进行实例变量的显示初始化扣喺,也就是执行在定义成员变量时就对其进行赋值的语句 6 执行当前构造方法的方式体中的程序代码 1):为什么super()和this()调用语句不能同时在一个构造函数中出现?
因为当在一个构造函函数中出现this()调用以后,那么去别外一个构造函数将也会直接默认或指定的super()方法
如要执行完成以后,返回到初始的构造函数还让执行super()方法时,那就又是重复操作了,无意义
所以编译也不会通过的 2):为什么super()和this()调用语句只能作为构造函数的第一句出现
如果不是作为第一句出现,编译也会出错的
如果选执行一些赋值语句,然后执行this或super()函数
那么就跟我们的执行流程相矛盾了
因为构造函数需要需要执执行this,如果没有this执行super()方法
编译器也不会让通过的 覆盖父类的方法
覆盖方法必须和被覆盖方法具有相同的方法名称,参数列表和返回值类型 如果在子类中想调用父类中那个被覆盖的方法,我们可以用super方法的格式 覆盖方法时,不能使用此父类中被覆盖的方法更严格的访问权限 final关键字
1 在java中声明类,属性和方法时,可以使用关键字final来修饰
2 final标记的类不能被继承
3 final标记的方法不能被子类重写
4 final标记的变量(成员变量或局部变量)即成为常量,只能赋值一次
5 方法中定义的内置类只能访问该方法内的final类型的局部变量
用final定义的局部变量相当于是一个常量,它的生命周期超出了方法运行的重命周期
将一个行参定义成final也是可以的,这就是限定了我们在方法中修改形式参数的值
6 public static final共同标记常量时,这个常量就成了全局常量 抽象类
java中可以定义一些不含方法体的方法,它的方法体的实现交给该类的子类根据自己的情况去实现
这样的方法就是抽象方法,包含抽象方法的类叫做抽象类 1 抽象类必须使用abstract关键字来修饰,抽象方法也必须用abstract来修饰
2 抽象类不能被实例化,也就是不能用new关键字去产生对象
3 抽象类只需声明,而不需实现
4 含有抽象方法的类必须声明为抽象类,抽象类的子类必须覆盖所有抽象方法后才能被实例化,否则这个子类还是个抽象类 */ //final class Person 将不能被继承了
class Person
{
//protected final String name = "unknown"; 变量为final时将不能被子类赋值了
protected String name = "unknown"; //public final String x = "abc"; //第一种赋值是初始赋值 public final String x;
//public static final String x; public static final String y = "abc"; public int age = -1; public Person()
{
this.x = "cde";
} public Person(String name, int age)
{
this.name = name;
this.age = age;
//或者在构造函数中进行赋值
this.x = "abc"; } //public void getInfo(){} 将不能在子类重写了
public void getInfo()
{
//this.x = "abc"; //用final定义的变量将不能被修改了
System.out.println("name:"+name+", age:"+age);
}
}; class Student extends Person
{ public String school = "unknown"; public Student()
{
//super("xlc",15);
super();
} public Student(String name, int age, String school)
{ this(name,age); //调用自己的构造函数
this.school = school;
//this(name,age); //调用自己的构造函数
} public Student(String name, int age)
{
super(name, age);
} public void getInfo()
{
System.out.println("school:"+school+"name:"+name+", age:"+age);
super.getInfo();
} public void study()
{ }
}; class TestStudent
{
public static void main(String[] args)
{ //Student st = new Student();
//st.name = "xlc";
//st.age = 34;
//st.getInfo(); Student st = new Student("xlc",22,"清华大学");
st.getInfo(); System.out.println(Float.MAX_VALUE);
}
};

  

/*
接口(interface)
如果一个抽象类中的所有方法都是抽象的,我们就可以将这个类用另外一种方式来定义,也就是接口定义
接口是抽象方法和常量值的定义的集合,从本质上讲,接口是一种特殊的抽象类
这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现 1 接口中的成员都是public访问类型的,接口的变量默认是用public static final标识的 2 我们可以定义一个新的接口用extends 关键字去继承一个已有的接口 3 我们也可以定义一个类用implements关键字去实现一个接口中的所有方法,我们还可以去定义一个抽旬类用implements关键字去实现一个接口中定义的部分方法 4 一个类可以继承一个父类的同时,实现一个或多个接口,extneds关键字必须位于implements关键字之前 对象的类型转换
1 子类对象可以自动转换成父类
2 父类转换为子类必须使用强制转换
3 instanceof操作符可以用它来判断一个实例对象是否属于一个类
4 Object类及equals方法 */
/*abstract class A
{
abstract int aa(int x, int y); //抽象类将不能实例化 }; class B extends A
{
int aa(int x, int y)
{ return 1;
}
};*/ interface Runner
{
int ID = 1; void run();
} interface Animal extends Runner
{
void breathe();
} class Fish implements Animal
{
public void run()
{
System.out.println("fish is swimming");
} //public void breathe()
public void breathe()
{
System.out.println("fish is bubbling");
} public static void main(String[] args)
{
Fish f = new Fish();
int j=0;
j = Runner.ID;
j = f.ID;
//f.ID = 2; //常量不能被赋值 }
}; abstract class LandAnimal implements Animal
{
public void breathe()
{ }
}; interface dog
{
void uaau();
} interface Flyer
{
void fly();
} class Bird implements Runner, Flyer
{
public void run()
{ } public void fly()
{ }
}; //继承一个类时,可以实现其它接口
//也是可以继承从外接口类的
class Student extends Person implements Runner, dog
//如果继承类和接口,extends必须在implements之前
{ public void run()
{ } public void uaau()
{ }
}; interface A
{
//public static final int ID=1;
//int ID = 1; //这个是一个常量而不是一个变量,接口只能定义常量,不能定义变量,
//只能定义常量和抽象类 public static final int ID=1; int aa(int x, int y); void bb();
} /*class
{
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}*/

  

/*
面向对象的多态性
1):应用程序不必为每一个派生类(子类)编写功能调用
只需要对抽象基类进行处理即可,这一招叫"以不变应万变",可以大大提高程序的可复用性 2):派生类的功能可以被基类的引用变量引用,这叫向后兼容,可提高程序的可扩充性和可维护性
以前写的程序可以被后来程序调用不足以为奇,现在写的程序(如callA方法)能调用以后写的程序(以后编写的一个类A的子类,如类D)就了不起了 */
class A
{
public void func1()
{
System.out.println("A func1 is calling");
} public void func2()
{
func1();
}
}; class B extends A
{
public void func1()
{
System.out.println("B func1 is calling");
} public void func3()
{
System.out.println("B func3 is calling");
}
}; class C
{
public static void main(String[] args)
{ B b = new B();
callA(b); //A aa = b;
//callA(new A());
} public static void callA(A a)
{
/*if(a instanceof B)
{
B b = (B)a; //强制类型转换
b.func1();
b.func2();
b.func3();
}else{
a.func1();
a.func2();
}*/ a.func1();
a.func2(); //a.func1();
//a.func2();
//a.func3();
}
}; class Student extends Object
{ private String name; private int age; public Student(String name, int age)
{
this.name = name;
this.age = age;
} /*public boolean equals(Object obj)
{
Student st = null;
if(obj instanceof Student)
{
st = (Student)obj;
if(st.name == name && st.age == age)
{
return true;
} else{
return false;
}
}else{
return false;
}
}*/
//如果没有覆盖父类的equals方法,那么将返回不等
//只是重载了一下函数 public static void main(String[] args)
{
Student st1 = new Student("张三",20);
Student st2 = new Student("张三",20);
if(st1.equals(st2))
{
System.out.println("相等");
}else{
System.out.println("不相等");
}
} }; /*class
{
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}*/

  

interface PCI
{
void start(); void stop(); } class NetWrokCard implements PCI
{
public void start()
{
System.out.println("Send...");
} public void stop()
{
System.out.println("stop...");
}
}; class SoundCard implements PCI
{
public void start()
{
System.out.println("du...");
} public void stop()
{
System.out.println("sound stop...");
}
}; class MainBoard
{
public void usePCICard(PCI p)
{
p.start();
p.stop();
}
}; class Assembler
{ public static void main(String[] args)
{
MainBoard mb = new MainBoard(); NetWrokCard nc = new NetWrokCard(); SoundCard sc = new SoundCard(); mb.usePCICard(nc);
mb.usePCICard(sc); //匿名类
/*mb.usePCICard(
new PCI()
{
public void start()
{
System.out.println("test start...");
} public void stop()
{
System.out.println("test end...");
}
}
);*/ //类拟于
class A implements PCI
{
public void start()
{
System.out.println("test start...");
} public void stop()
{
System.out.println("test end...");
} };
mb.usePCICard(new A()); }
};