Java基础<六>---> 面向对象与java特性(封装、继承、多态

时间:2022-01-16 19:38:36

第一 封装

一、概述

1、定义:封装是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

2、好处:

a.将变化隔离

b.便于使用

c.提高重用性

d.提高安全性

3、原则:

a.将不需要对外提供的内容隐藏起来

b.把属性都隐藏,提供公共方法对其访问

4、说明:

a.私有仅仅是封装的一种表现形式,如包也是一种封装形式

b.之所以对外提供访问方式,就是因为可以在访问方式中加入逻辑判断等语句,对访问的数据进行操作,提高了代码的健壮性。

第二 继承

一、概述

       当两个事物之间存在一定的所属关系,就像学生和工人都是人,也都具有人的共同特性如姓名等,我们就把人封装成一个类(这个类中存放共性的成员),然后在分别定义学生和工人这两个类中让他们分别继承人这个类,在人与学生和人与工人之间就有了所属关系这种就称为继承,从而学生和工人就具有了人的特性。在java中一个继承的类(为子类)可以从被继承的类(为父类或者超类)中获得一些属性和方法,而不必再自己创建新方法(在不需要复写的情况等)。

、特点:

1、提高代码复用性,定义在父类中的成员(变量和方法),可以被子类重复使用;

2、让类与类之间产生关系,这样就会有多态的特性。使得应用起来更方便。

需要注意的是:

A.不可以只是为了获取其他类的功能,简化代码就一味的使用继承;必须是类与类之间有所属关系,才可以用继承,这种关系称为“is-a”。

B.java语言中,只支持单继承,不支持多继承。究其原因,是因为多继承容易带来安全隐患:

a.当多个父类中定义了相同的功能,且功能内容不同时,子类对象并不确定要运行哪一个,这就造成了程序的混乱而导致异常出现。

b但是java保留了这种机制,并改良了多继承为多实现,而且接口就可以多继承。

三、使用继承体系中的功能

1、如果使用体系,要先对体系中父类的描述进行参阅,了解父类中的共性功能,即可以使用该体系了。这样既可以减少查阅时间,也能更系统的了解体系结构,以及父类的功能。

2、具体调用父类中的功能的时候,需要创建子类对象,通过子类对象对父类方法调用,实现继承。为何要通过创建子类对象调用父类中的方法呢?原因如下:

        a.父类很可能不可以创建对象,如父类是一个抽象类或者接口,这就需要子类创建对象,调用方法。

        b.创建子类对象,可以使用更多的功能,如父类公有的,和子类中自定义的特有功能。

单一句话:查阅父类功能,创建子类对象使用功能。

四、子父类出现后,类成员的特点:类成员:变量、函数、构造函数

1、变量:

        子父类中出现非私有的同名成员变量是,子类访问本类的同名时,要用this关键字(如果省略了this,仍是代表本类的变量);子类访问父类同名变量时,用super关键字。

        补充:this和super两者都存在与方法区中。

           this:本类对象引用,那个对象调用this所在的函数,this就代表那个对象。

           super:父类对象引用,用于子类初始化父类构造函数、调用父类成员等。

           this和super不能同时存在与构造函数中。

2、.函数:(覆盖(重写))

当子类同父类出现相同函数时,子类对象调用该函数时,会运行子类内容,如同覆盖谷类函数一样。实际上并没有覆盖父类的函数,如果还需要调用父类的这个方法,需要用super.方法名即可。
class Fu{
Fu(){
}
void method(){
System.out.println("Fu......");
}
}

class Zi extends Fu{
Zi(){
//super();//隐式的super语句,调用父类中默认的无参构造函数
//子类比有调用父类构造函数的地方,因为子类必须知道父类成员变量的初始化,才能操作其变量
//this和super不能同时存在,因为他们都必须在构造函数的第一行,这是因为他们都是查看构造函数的初始化的
//构造函数不存在重写
}
void method(){//重写,当对象调用时,执行重写后的函数
System.out.println("Zi......");
}
}

重写的应用:

      1、当子类继承了父类就沿袭了父类的功能,在子类中虽然具备此功能,但是功能主体却不一样,此时就需要重写父类中的方法,以达到功能扩展的效果。

注意:

       1、子类权限必须大于或等于父类权限才能覆盖

       2、静态只能覆盖静态,这个一般不用,因为被覆盖后在多态中是静态加载的,容易出问题。

3、构造函数

       子类继承了父类也就具备了父类的属性(变量)和功能(方法),所以在加载子类对象之前,子类需要先知道父类构造函数是怎么对其成员变量进行初始化的。也就是因为这样,所以子类的构造函数的第一行都有一条隐式的super();以调用父类的默认的构造函数。如果父类自定义了构造函数,且没有无参的构造函数,这时就需要我们通过super(参数)区自己制定调用父类的构造函数。而且子类必有一个构造函数会访问父类的构造函数。

补充:

因为继承是对封装性的一个极大挑战,所以就引入了final关键字

       final:根据程序上下文环境,Java关键字final有“这是无法改变的”或者“终态的”含义,它可以修饰非抽象类、非抽象类成员方法和变量。你可能出于两种理解而需要阻止改变。 
final类不能被继承,没有子类,final类中的方法默认是final的。 
final方法不能被子类的方法覆盖,但可以被继承。 
final成员变量表示常量,只能被赋值一次,赋值后值不再改变。 
final不能用于修饰构造方法。 

 第三 多态

一、概述:

多态:可以理解为事物之间存在多种形态。

如:人有男人和女人。其中男人可以称为男人,也可以称为人

二、多态的体现:

1、父类的引用指向了自己的子类对象

2、父类的引用页可以接受自己的子类对象

如:Person p = new Student();这句话就是在栈内存中产生一个p,然后在堆内存中产生一个Student的对象,然后把Student的对象地址值赋给p,也就是p就指向了Student的对象。

三、多态的前提:

1、必须是类与类之间存在着关系,要么继承、要么覆盖。

2、通常还有一个前提:存在覆盖

四、多态的利弊:

1、好处:大大的提高了程序的扩展性

2、弊端:虽然提高了扩展性,但是只能使用父类的父类的引用访问父类中的成员,不可预先使用子类。这是因为子类在父类之后加载。

Animal a = new Cat();//类型提升,可以调用共性方法
Cat c = (Cat)a;//强转回所属类型,只有这样才能调用子类中特有的方法

注意:

1、不能将父类对象转换成子类类型

2、只有父类引用指向自己子类对象才能转换,可类型提升,也可以强转回子类

3、多态至始至终都是子类在做着变化

abstract class Animal
{
abstract void eat();

}

class Cat extends Animal
{
public void eat()
{
System.out.println("吃鱼");
}
public void catchMouse()
{
System.out.println("抓老鼠");
}
}


class Dog extends Animal
{
public void eat()
{
System.out.println("吃骨头");
}
public void kanJia()
{
System.out.println("看家");
}
}


class Pig extends Animal
{
public void eat()
{
System.out.println("饲料");
}
public void gongDi()
{
System.out.println("拱地");
}
}

//-----------------------------------------


class DuoTaiDemo
{
public static void main(String[] args)
{
//Cat c = new Cat();
//c.eat();

//Dog d = new Dog();
//d.eat();
//Cat c = new Cat();
/*
Cat c1 = new Cat();
function(c1);

function(new Dog());
function(new Pig());
*/

//Animal c = new Cat();
//c.eat();


function(new Cat());
function(new Dog());
function(new Pig());



}
public static void function(Animal a)//Animal a = new Cat();
{
a.eat();
//a.catchMouse();
}
/*
public static void function(Cat c)//
{
c.eat();
}
public static void function(Dog d)
{
d.eat();
}

public static void function(Pig p)
{
p.eat();
}
*/

}

五、多态的特点:

1、成员函数的特点:

    编译时期:参阅引用型变量所属的类中是否有调用的方法,如果有编译通过,没有则编译失败。

    运行时期:参阅对象所属的类中是否有调用的方法

总结:成员函数在多态调用是,编译时看左边,运行看右边。子类局部有变量就访问局部的,没有就访问子类全局的,子类没有就访问父类的

2、在多态中成员变量和静态的特点:

    无论编译和运行都参考左边,即是引用型变量所属的类型。也就是说父类中有就先找父类的。

    非静态有重写方法,静态一般不被重写

    因为当调用静态方法是,只要建立子类对象,父类与子类的静态方法都会随之加入方法区内存中,这就不需要对象直接可以用类名调用,只要引用还存在,就看引用变量的类型。

六、多态的应用:

1、定义好工具类,就是共同行为封装在一个类中

2、对类型进行抽取-->多态的产生

3、操作同一个大类型,对其中的小类型都可以操作