一、继承
好处:
1:提高了代码的复用性。
2:让类与类之间产生了关系,提供了另一个特征多态的前提。
形式:
classSubDemoextends Demo{}
<span style="font-size:18px;">class Personnel
{
String name;//姓名
String sex;//性别
int age; //年龄
void show(){
System.out.println("大家好,我叫:" + name +
",性别:" + sex +
",年龄:" + age);
}
}
class Student extends Personnel{
String classNo; //学号
}
class Teacher extends Personnel{
String subject;//学科
}
class Employee{
String dept; //部门
}
class Demo
{
public static void main(String[] args)
{
Student stu = new Student();
stu.name = "刘德华";
stu.sex = "男";
stu.age = 20;
stu.show();
Teacher tea = new Teacher();
tea.name = "章子怡";
tea.sex = "女";
tea.age = 18;
tea.show();
}
}
</span>
这样,即沿袭了父类的功能,又定义了子类特有的内容。
2)重写的规则:
子类方法的:返回值类型、方法名、参数列表:必须完全相同;
如果只有返回值类型、方法名:编译可以通过,此方法认为是子类自己的方法
如果只有方法名、参数列表相同,返回值不同:编译错误.不能重写,要求返回值类型必须相同;
2.当实例化子类对象时,会先实例化一个父类对象,会隐式的调用父类默认的构造方法,会在子类的
构造方法的第一句话添加一句:super();
3.如果父类没有默认构造方法时,子类必须显示的调用父类的带参构造方法,需要使用关键字super();
4.当子类覆盖了父类的成员时,在子类中可以使用super.XXX来访问父类中被覆盖的成员;
class Student extends Personnel{
public int num = 20;//可以,子类的成员覆盖父类的成员
private String no = "b";
Student(){
super();
System.out.println("构造了一个Student = " + no );
}
Student(String name){
super(name);
System.out.println("带一个参数的Student构造器");
}
void show(){
int num = 30;
System.out.println("num = " + num);//使局部变量
System.out.println("this.num = " + this.num);//本类自己的
System.out.println("super.num = " + super.num);//父类的
}
//重写了父类的say();
//@Override//重写标记,编译器按照重写规则验证方法,不符合重写规则的方法,不能通过编译;
void say(){super.say();
System.out.println("我是传智播客的一名学生!我骄傲!!");
}
//可以编译,和父类的void say()不是重写关系,是属于两个方法
void say(String str){
System.out.println("我是传智播客的一名学生!我骄傲!!");
}
//编译失败,方法名、参数列表完全相同,但返回值类型不同,要求返回值类型必须相同;
/* int say(){
}
*/
}
class Teacher extends Personnel
{
Teacher(){
super("");
System.out.println("构造了一个Teacher");
}
}
class Demo
{
public static void main(String[] args)
{
Student stu = new Student("刘德华");
stu.say();
// Teacher tea = new Teacher();
}
}
f inal特点:
1:这个关键字是一个修饰符,可以修饰类,方法,变量。
2:被final修饰的类是一个最终类,不可以被继承。
3:被final修饰的方法是一个最终方法,不可以被覆盖。
4:被final修饰的变量是一个常量,只能赋值一次。
class Const{
public static final double PI = 3.14159;
}
class Personnel{
final int num;
final static int num2 = 20;
Personnel(){
num = 10;
}
String name;
final void say(){
System.out.println("我是传智播客的一员");
}
}
class Student extends Personnel{
//不能重写父类的final方法
/* void say(){
}
*/
}
class Demo
{
public static void main(String[] args)
{
System.out.println(Const.PI);
}
}
抽象
抽象定义:
抽象就是从多个事物中将共性的,本质的内容抽取出来。
例如:狼和狗共性都是犬科,犬科就是抽象出来的概念。
抽象类:
Java中可以定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类。
抽象方法的由来:
多个对象都具备相同的功能,但是功能具体内容有所不同,那么在抽取过程中,只抽取了功能定义,并未抽取功能主体,那么只有功能声明,没有功能主体的方法称为抽象方法。
1:抽象方法只能定义在抽象类中,抽象类和抽象方法必须由abstract关键字修饰(可以描述类和方法,不可以描述变量)。
2:抽象方法只定义方法声明,并不定义方法实现。
3:抽象类不可以被创建对象(实例化)。
4:只有通过子类继承抽象类并覆盖了抽象类中的所有抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。
5: 抽象类只能单继承。
抽象类的细节:
1:抽象类中是否有构造函数?有,用于给子类对象进行初始化。
2:抽象类中是否可以定义非抽象方法?
可以。其实,抽象类和一般类没有太大的区别,都是在描述事物,只不过抽象类在描述事物时,有些功能不具体。所以抽象类和一般类在定义上,都是需要定义属性和行为的。只不过,比一般类多了一个抽象函数。而且比一般类少了一个创建对象的部分。
3:抽象关键字abstract和哪些不可以共存?final , private , static
4:抽象类中可不可以不定义抽象方法?可以。抽象方法目的仅仅为了不让该类创建对象。
<span style="font-size:18px;">abstract class Personnel
{
abstract void say();
}
class Student extends Personnel
{
//必须要重写父类的抽象方法
void say(){
System.out.println("我是传智播客的一名学生");
}
}
class Teacher extends Personnel
{
//必须要重写父类的抽象方法
void say(){
System.out.println("我是传智播客的一名教师");
}
}
//一个抽象类可以继承另一个抽象类
abstract class B extends Personnel
{
}
class Demo
{
public static void main(String[] args)
{
Student stu = new Student();
stu.say();
}
}</span>
接 口
interface {}
接口是对外暴露的规则。
接口是程序的功能扩展。
接口的出现降低耦合性。
接口可以用来多实现。
类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。
接口与接口之间可以有继承关系
1:抽象类只能被继承,而且只能单继承。
接口需要被实现,而且可以多实现。
2:抽象类中可以定义非抽象方法,子类可以直接继承使用。
接口中都有抽象方法,需要子类去实现。
3:抽象类使用的是 is a 关系。
接口使用的 like a 关系。
4:抽象类的成员修饰符可以自定义。
接口中的成员修饰符是固定的。全都是public的。
interface IA{
void f1();
void f2();
}
interface IB{
void f2();
void f3();
}
interface IC extends IA,IB
{
void f4();
}
class C
{
}
class A extends C implements IC{//多实现
public void f1(){
}
public void f2(){
}
public void f3(){
}
}
class Demo
{
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}
二、多态
函数本身就具备多态性,某一种事物有不同的具体的体现。
体现:父类引用或者接口的引用指向了自己的子类对象。//Animal a = new Cat();
多态的好处:提高了程序的扩展性。
多态的弊端:当父类引用指向子类对象时,虽然提高了扩展性,但是只能访问父类中具备的方法,不可以访问子类中特有的方法。
多态的前提:
1:必须要有关系,比如继承、或者实现。
2:通常会有覆盖操作。
class Animal
{
void run(){
System.out.println("跑");
}
}
class Cat extends Animal
{
}
class Dog extends Animal
{
}
class Demo
{
public static void main(String[] args)
{
//正常写法:
Cat cat = new Cat();
cat.run();
//多态的写法:
//一个父类的引用指向了它的一个子类的对象
Animal anmObj = new Cat();
anmObj.run();
Animal anmObj2 = new Dog();
anmObj2.run();
}
}
匿名内部类:
没有名字的内部类。就是内部类的简化形式。一般只用一次就可以用
这种形式。匿名内部类其实就是一个匿名子类对象。想要定义匿名内部类:需要前提,内部类必须继承一个类或者实现接口。
匿名内部类的格式:new 父类名&接口名(){ 定义子类成员或者覆盖父类方法 }.方法。
匿名内部类的使用场景:
当函数的参数是接口类型引用时,如果接口中的方法不超过3个。可以通过匿名内部类来完成参数的传递。
其实就是在创建匿名内部类时,该类中的封装的方法不要过多,最好两个或者两个以内。
interface IA{
void show();
}
class Demo {
public static void main(String[] args){
fun(
new IA(){
//重写的方法
public void show(){
System.out.println("HelloWorld");
}
}
);
fun3(
new IA(){
//重写方法
public void show(){
System.out.println("你好中国!");
}
}
);
}
public static void fun(IA aObj){
aObj.show();
}
public static void fun3(IA aObj){
aObj.show();
}
}