第七天总结
1、 抽象类
a.通过一个abstract关键字来修饰的类
b.主函数,一般函数,构造函数,抽象函数的区分,抽象类是由抽象方法(函数)引出来的。抽象类是因为抽象方法的由来而由来。抽象类不能被实例化
abstract class absdemo
{
abstract void show();
}
c.抽象类不能被new对象,也就是抽象类不能建立对象,因为抽象类中的抽象函数是没有函数主体,通常,建立一个抽象类的子类,在子类中用函数将抽象类中的所有抽象函数覆盖掉,从而能够建立子类的对象。完成实例化
d.抽象方法的出现可以强制子类去做某些事情,因为如果子类要实例化,就必须要覆盖掉父类中的抽象方法。
e.如果子类没有把抽象类中的抽象函数全部覆盖,那么这个子类仍然还是一个抽象类,必须进一步定义子类对抽象函数进行抽象化才能类的实例化
f.抽象类也是又类不断向上抽取而产生的,但是有些行为在各个对象中的实现方法是不一样的,所以最顶层的父类中就没法给出一个确定的方法,所以他的函数主体就是空的,从而衍化成了抽象函数,就形成了抽象类
g.抽象类一定是父类,但是他仍然可以做其他抽象类的子类
h.抽象类中可以不写抽象方法,或者抽象类中的方法不一定全部是抽象方法
i.abstract和final不能同时修饰类名,final是最终化类,他不能被继承,他没有自己的子类,而abstract是必须有子类才能被实例化的。
j.抽象方法可以写public 但是不能用private,因为private修饰的私有函数,不能被覆盖,同样,抽象方法也不能写成静态,因为static是随着类的加载而加载,而抽象类只有在子类创建了对象后才能实例化,如果有了static的话那么在子类没有创建对象之前,他所修饰的函数已经被加载进了内存,而抽象函数被加载是没有意义的
k.抽象类中是存在构造函数,子类在对象生成的时候,先要去父类对父类进行构造函数初始化。
l.抽象类和一般的类是没有区别的,仅仅是多了抽象方法而已,有了抽象方法所有类也就被抽象了,变成了抽象类。
2、接口
我们刚开始学接口的时候可以这么想,接口在程序中体现就是一种特殊的抽象类,接口里面的函数全部都是抽象函数。
没有抽象的变量一说,接口里的变量都被final修饰,被最终化了,就相当于是一个常量,见后面他的写法。
a.定义接口的关键字,interface。
b.接口也不能创建对象,他里面是抽象的方法,他只能创建自己的子类去实例化。如果他的子类没有覆盖掉所有的抽象方法那么这个子类还是个抽象类
c.只能存放两种成员,一个是函数,一个是变量,他们都有固定修饰符
变量:public static final 数据类型 变量名=值 他就相当于一个常量
函数:public abstract 返回值类型 函数名(参数列表);
在接口中,你可以省略数据类型和返回值类型前面的所有修饰符,但是可以省略不代表没有,洗头会默认给你隐藏起来,其实是有的
d.接口的子类不叫继承接口,子类只能说是实现接口,用关键字implements表示
接口的特点(主板实例)
a.接口是对外暴露的一种规则
b接口是程序功能的扩展
c.接口可以降低程序的耦合性(事物的紧密联系程度)即互相依赖性
d.接口可以被多实现,相当于多继承,一个子类可以实现多个接口,因为接口中的函数都是没有主体的,即使有完全相同的抽象函数,也可以被子类被覆盖实现
接口的应用
当我们继承一个类的时候,仍然同时去实现接口,要先继承后实现。
interface A
{
void show();
}
interface B
{
void show();
}
class Demo
{
public void show(){}
}
class inter extends Demo implements A,B
{
}
实例理解:学员继承学员类中的学习的方法,然后部分学员又实现了抽烟的接口。抽烟不是通用功能,而是扩展功能,不是所有学员对象所共有的,所以我们可以定义一个抽烟的接口。
类与类之间是继承关系,类与接口之间是实现关系,因为接口中就没有一个能用的东西。但是接口与接口之间也是可以继承的。并且支持多继承,一个接口可继承多个接口
之所以类之间没有多继承,我们可以用一个下面的例子推理,但是接口中的函数都是没有主体的,没法实例化的,最后你在实现的时候实现的是哪个函数,他就给你哪个函数,不存在安全隐患,所以多继承在接口之间是可以的。
class A
{
int show(){}
}
class B
{
char show(){}
}
class C extends A,B
{
int show(){}
}
在这个例子中,C同时继承了A和B,那么C的show函数就需要覆盖两个父类中show函数,在覆盖A的时候是没问题的,但是他没法去覆盖B中的show函数,因为返回值类型是不一样的,但是当创建C的对象并调用它的show方法的时候,C就会去A和B中去找到show函数,这个时候就没法确定如否执行B中的show,这样就出现了不稳定因素,那么这就是个安全隐患。
3、多态
函数也有多态性,比如说覆盖、重载。
对象的多态性可以描述为某一类事物的多种存在形态。人有男人的存在形式也有女人的存在形式。
a.多态性的前提条件是多种存在形态之间一定要有关系。因为关系的存在才有的多态性
class Animal
{
void show1()
{
System.out.println(“animal show1”);
}
void show2()
{
System.out.println(“animal show2”);
}
}
class Dog
{
void show1()
{
System.out.println(“dog show1”);
}
void show3()
{
System.out.println(“dog show3”);
}
}
class Demo
{
public static void main(String[] args)
{
//Dog d=new Dog(); 首先我们可以通过创建子类的对象覆盖父类中的对象,老办法
Animal a=new Dog();//父类的引用指向子类的对象,多态在程序中的一种体现。
a.show1();//可以编译,输出的子类中的show1
a.show2();//可以编译,输出的是父类中的show2,因为子类没有将其覆盖
a.show3()//不能编译,
/*
上面show3不能编译的时候原因如下,因为JAVA在编译的时候对象是还没有建立的,所以在编译的时候本例中的子类对象还没建立,show1,show2在父类中都能找的到,但是show3找不到,所以不能编译。具体讲解见下面d项
*/
}
void show(Animal a)//父类的引用接收子类的对象,多态在程序中的另外一种体现
{
}
}
b.上例总结:在多态性当中,成员函数在编译时期看的是引用型变量所属的类中是否有所调用的方法,(上例中的的a就是一个引用型变量,他引用的是Dog类的对象,运行时期,看的是对象所属的类中是否有所调用的方法。上面的show1被子类覆盖,show2被子类继承。
也就是成员函数编译看左边,运行看右边。、
c.如果在上例中是可以调用show3的,我们可以联想到数据运算时候的自动类型提升和强制类型转换,show3是子类的特有属性,我们可以用Dog d=(Dog)f;在输入d.show3()就可以转换了,形同于强制类型转换。在多态的过程中,自始至终只有一个对象。
d.多态的出现增强的程序的扩展性。要有关系,要有覆盖。接口的引用也可以指向引用对象
e.对象 instanceof 接口或者类,就是判断对象是否所属于右边的接口或者类
f.当要指挥多个对象做事情的时候,调用多个对象的方法的时,而这些对象所属的类又属于同一个父类,那么我们可以用多态是实现对他们的进行统一指挥使用,方便,提高了程序的扩展性,但是唯一的缺点就是没法体现出子类对象中的特殊函数。多态实现的函数只能是父类中已有的。
多态的应用举例:
/*
多态的一种应用形式,也是比较常见的一种,父类引用接收了子类的对象,下面的例子在以前我们是可以直接在主函数创建张三李四等对象的,直接调用它们的方法;但是如果想张三李四这样的类多了的话,就会比较麻烦,还有一种情况,如果人这个类不只一种行为,不光有吃饭,还有睡觉等等等等,那么我们在主函数中如果直接建立张三等对象的话,要实现它们中的每个方法我们就必须指挥它们里面的所有方法,就更麻烦了,所以我们直接创建一个personEat的类,拿吃说吧,person的所有子类比如张三等都有吃的方法,那么我们就可以在personEat中建立一个开吃的类,用于指挥吃饭这个方法,因为person p这个父类引用时可以接收子类的对象的,所以可以往里面传张三李四等对象读取到他们吃饭的方法,同理睡觉等等方法,都可以用这种方法得到简便的指挥,这就是多态的一种应用。
*/
abstract class person
{
abstract void eat();
}
class personEat
{
void eating(person p)//这里的参数是用来接受子类对象
{
p.eat();//子类对象在执行自己的函数之前先要去看父类中的相同的函数,再覆盖掉
}
}
class zhangsan extends person
{
void eat()
{
System.out.println("yumi");
}
}
class lisi extends person
{
void eat()
{
System.out.println("xiaomai");
}
}
class wangwu extends person
{
void eat()
{
System.out.println("dami");
}
}
class test4
{
public static void main(String[] args)
{
personEat e=new personEat();//建立一个开吃类的对象
e.eating(new zhangsan());//括号中是建立一个子类张三的对象引用给person类变量
e.eating(new lisi());
e.eating(new wangwu());
}
}