面向对象的三大特性

Java三大特性

封装

对象是实体,需要被创建,可以为我们做事情

类是规范,根据类的定义来创造对象

对象(这只猫)

表达东西或事件

运行时相应消息(提供服务)

类(猫)

定义所有猫的属性

就是Java中的类型

可以用来定义变量

image-20210131124458633

对象 = 属性 + 操作

数据:属性或状态

操作:函数

image-20210131124954908

这些操作保护这些数据,数据是不对外公开的,这叫做封装。只需要调用,不需要关心内部操作。

继承(共性提取)

面向对象程序设计语言有三大特性:封装、继承和多态性。继承是面向对象语言的重要特征之一,没有继承的语言只能被称作“使用对象的语言”。继承是非常简单而强大的设计思想,它提供了我们代码重用和程序组织的有力工具

我们把用来做基础派生其它类的那个类叫做父类、超类或者基类,而派生出来的新类叫做子类。Java用关键字extends表示这种继承/派生关系:

class ThisClass extends SuperClass {
	//… 
}

继承表达了一种is-a关系,就是说,子类的对象可以被看作是父类的对象。比如鸡是从鸟派生出来的,因此任何一只都可以被称作是一只鸟。但是反过来不行,有些鸟是鸡,但并不是所有的鸟都是鸡。如果你设计的继承关系,导致当你试图把一个子类的对象看作是父类的对象时显然很不合逻辑,比如你让鸡类从水果类得到继承,然后你试图说:这只本鸡是一种水果,所以这本鸡煲就像水果色拉。这显然不合逻辑,如果出现这样的问题,那就说明你的类的关系的设计是不正确的。Java的继承只允许单继承,即一个类只能有一个父类

对理解继承来说,最重要的事情是,知道哪些东西被继承了,或者说,子类从父类那里得到了什么。答案是:所有的东西,所有的父类的成员,包括变量和方法,都成为了子类的成员,除了构造方法。构造方法是父类所独有的,因为它们的名字就是类的名字,所以父类的构造方法在子类中不存在。除此之外,子类继承得到了父类所有的成员。

但是得到不等于可以随便使用。每个成员有不同的访问属性,子类继承得到了父类所有的成员,但是不同的访问属性使得子类在使用这些成员时有所不同:有些父类的成员直接成为子类的对外的界面,有些则被深深地隐藏起来,即使子类自己也不能直接访问。下表列出了不同访问属性的父类成员在子类中的访问属性:

父类成员访问属性 在父类中的含义 在子类中的含义
public 对所有人开放 对所有人开放
protected 只有包内其它类、自己和子类可以访问 只有包内其它类、自己和子类可以访问
缺省 只有包内其它类可以访问 如果子类与父类在同一个包内:只有包内其它类可以访问否则:相当于private,不能访问
private 只有自己可以访问 不能访问

public的成员直接成为子类的public的成员,protected的成员也直接成为子类的protected的成员。Java的protected的意思是包内和子类可访问,所以它比缺省的访问属性要宽一些。而对于父类的缺省的未定义访问属性的成员来说,他们是在父类所在的包内可见,如果子类不属于父类的包,那么在子类里面,这些缺省属性的成员和private的成员是一样的:不可见。父类的private的成员在子类里仍然是存在的,只是子类中不能直接访问。我们不可以在子类中重新定义继承得到的成员的访问属性。如果我们试图重新定义一个在父类中已经存在的成员变量,那么我们是在定义一个与父类的成员变量完全无关的变量,在子类中我们可以访问这个定义在子类中的变量,在父类的方法中访问父类的那个。尽管它们同名但是互不影响。

在构造一个子类的对象时,父类的构造方法也是会被调用的,而且父类的构造方法在子类的构造方法之前被调用。在程序运行过程中,子类对象的一部分空间存放的是父类对象。因为子类从父类得到继承,在子类对象初始化过程中可能会使用到父类的成员。所以父类的空间正是要先被初始化的,然后子类的空间才得到初始化。在这个过程中,如果父类的构造方法需要参数,如何传递参数就很重要了。

**子类也会继承父类的父类的所有的属性和方法(但不能直接访问private成员) **

如果不写extends, Java类都默认继承java.lang.Object类 Java所有类从java.lang.Object开始,构建出一个类型继承树 Object类里面默认就有clone, equals, finalize, getClass,hashCode, toString等方法

每个Java类都必须有构造函数。如果没有显式定义构造函数, Java编译器自动为该类产生一个空的无形参构造函数。如果已经有了显
式的有参构造函数,编译器就不会越俎代庖了。
**每个子类的构造函数的第一句话,都默认调用父类的无参数构造函数super(),除非子类的构造函数第一句话是super,而且super语句必须放在第一条,不会出现连续两条super语句。 **

**总结
– 子类继承父类们所有的东西(但不能直接访问private成员)
– Java所有类都继承自java.lang.Object类
– Java所有的类都是单根继承的
– 子类构造函数默认第一句话都会去调用父类的构造函数 **

抽象类和接口

抽象类和接口时Java继承体系中非常重要的组成部分

类:属性(零个或者多个)+方法(0个或者多个)

一个完整的类/健康的类:所有的方法都有实现 (方法体)

类可以没有方法,但是有方法就一定要实现,这才是一个完整的类。

一个完整的类才可以被实现,被new出来

如果一个类暂时有方法未被实现,(只有方法名字,形参列表,没有方法体)那所在的类就被定义为抽象类。

public abstract class shape{

	int area;

	public abstract void calArea();

}

抽象类关键字abstract声明

抽象类的组成

(optional)成员变量,个数不限

(optional)具体方法,方法有实现,个数不限

(optional)抽象方法,加abstract关键字,个数不限

有一个抽象方法,一定要声明成抽象类,abstract类是没办法new的

抽象类也是类,一个类继承抽象类,就不能在继承于其他的(抽象)类

子类可以继承类于抽抽象类,但是一定要把父类的抽象类全部实现,如果不能全部实现,那子类也必须被定义为抽象类

只有实现父类(们)的所有抽象方法,才成为完整的类

如果类的所有方法都没实现,那么这个类就算是接口interface(不算类,或者说特殊的类,编译出来也是.class)

public interface Animal{

​ public void eat();

​ public void move();

}

类只可以继承(extends)一个类,但可以实现(implements)多个接口,继承和实现可以同时

继承抽象类,必须实现所有的abstract的方法,实现多个接口,必须实现接口所定义的所有方法。接口设计为了弥补单根继承的去缺陷

一个类方法,只会在当前类或者父类实现,肯定不会在所实现的父类接口中定义。

接口可以继承(多个)接口,没有实现的方法将会叠加,类实现接口,就必须实现所有未实现的方法如果没有全部实现,那么只能成为一个抽象类。接口里可以定义变量,但是一般是常量,可以参考final。

抽象类和接口相同点:两者都不能被实例化,不能new操作
抽象类和接口不同点:
– 抽象类abstract, 接口interface
– 抽象类可以有部分方法实现,接口所有方法不能有实现
一个类只能继承(extends)一个(抽象)类,实现(implements)*多个接口
– 接口可以继承(extends)多个接口
抽象类有构造函数,接口没有构造函数
抽象类可以有main,也能运行,接口没有main函数
– 抽象类方法可以有private/protected, 接口方法都是**public **

多态

多态就是有多种形态

**extends继承或者implements实现是多态的前提 **

image-20210131142956458

代码当中体现多态性性就是一句话:父类引用指向子类对象

格式:

父类名称 对象名 = new 子类名称()

或者:

接口名称 对象名 = new 实现类名称()

左夫右子就叫多态

子类对象当作父类对象来使用,一只猫当作动物来使用

public class Demo06Muti {
    public static void main(String[] args) {
        //使用多态的写法
        //左侧父类的引用,指向了右侧子类的对象
        Fu obj = new Zi();
        obj.method();
        obj.methodFu();
    }
}

多态成员变量的使用特点

与继承变量相比没有任何变化。
访问成员变量的两种方式:
1.直接通过对象名称访问成员变量,看等号左边是谁,优先用谁,没有则向上找,不会向下找
2.间接通过成员方法访问成员变量,看该方法属于谁,优先用谁,没有则向上找

public class Demo06Muti {
    public static void main(String[] args) {
        //使用多态的写法
        //左侧父类的引用,指向了右侧子类的对象
        Fu obj = new Zi();
        System.out.println(obj.num);//10
        obj.showNum();//子类没有覆盖重写,就是父,如果覆盖重写,就是子
    }
}

成员方法也没有变

在多态的代码当中,成员方法的方法规则:
看new的是谁,就优先用谁,没有就向上找

注意:编译看左边,运行看右边

public class method {
    public static void main(String[] args) {
        Fu obj = new Zi();//多态
        obj.method();//父子都有,优先用子
        obj.methodFu();//子类没有,父类有,找到父类
        //编译看左边,左边是父,没有methodZi
        //obj.methodZi();//错误写法
    }
}

对比:

成员变量:编译看左边,运行还看左边。
成员方法:编译看左边,运行看右边

如何才能知道一个父类引用的对象,本来是什么子类?

格式:

对象 instanceof 类名称

这将得到一个boolean值结果,也就是判断前面的对象能不能当作后面类型的实例。

变量支持互相转化,比如 int a = (int) 3.5;
类型可以相互转型,但是只限制于有继承关系的类。
– 子类可以转换成父类,而父类不可以转为子类。
– 子类继承父类所有的财产,子类可以变成父类(从大变小,即向上转型);从父类直接变成子类(从小变大,即向下转型)则不允许。

image-20210131133700259

父类转为子类有一种情况例外
就是这个父类本身就是从子类转化过来的

image-20210131133549565

obj1本身起源就是来自Man

image-20210131181234174image-20210131181330633

类型转换,带来的作用就是多态。
• 子类继承父类的所有方法,但子类可以重新定义一个名字、参数和父类一样的方法,这种行为就是重写(覆写,覆盖,overwrite/override, not overload(重载))。

重载:函数名一样,形参不一样

重写:子类的方法替换掉父类的方法

子类的方法的优先级高于父类的。

多态的作用
– **以统一的接口来操纵某一类中不同的对象的动态行为
– 对象之间的解耦 **

image-20210131175939917

posted @ 2021-01-31 23:25  老虎彡  阅读(2535)  评论(0)    收藏  举报