面向对象、继承、接口、抽象类

来源:互联网 发布:软件解决方案模板 编辑:程序博客网 时间:2024/05/02 02:33

 

一.面向对象

1.面向对象与面向过程的区别:

(1)面向过程强调功能

(2)面向对象强调具有功能的对象

举例:面向过程:打开冰箱——>把大象装进冰箱——>关闭冰箱;面向对象的思想就是强调具有功能的对象:冰箱打开,冰箱存储,冰箱关闭。

面向对象是一种思想,万物皆对象,程序是对象的集合,他们通过发送消息来告诉彼此所要做的;每个对象都有自己的由其他对象所构成的存储,这样可以构建复杂的体系,同时将复杂性隐藏在对象的简单性背后;每个对象都拥有其类型,每个类区别于其他类的特性就是可以发送什么消息给它。某一特定类型的所有对象都可以接受同样的信息,性质相同的事物可以交互(java in thinking 抄的,哈哈哈!)

简单的说,面向对象的特点:

        1. 是一种解决问题的思想

        2. 可以将复杂的事情简单化

        3.将程序员从执行者转换成了指挥者

        4. 完成需求时:

                a)先要去找具有所需的功能的对象来用。

                b) 如果该对象不存在,那么创建一个具有所需功能的对象。

                c) 这样简化开发并提高复用。
2.面向对象三个特征:
封装,继承,多态
 开发就是找对象,使用,没有对象,就创建一个对象
简单的说就是找对象,建立对象,使用对象,维护对象的关系

3.类和对象的关系
现实生活中的对象,张三,李四
想要描述:提取对象中共性内容,对具体的抽象
描述时:这些对象的共性有:姓名,年龄,性别,学习java的功能

映射到java中就是class定义的类
具体对象就是对应java在堆内存中用java建立的实体;

类就是对现实生活中事物的描述。
对象就是这类事物实实在在存在。

对于计算机语言是先有类的个体
对于现实生活是先有对象
需求:描述汽车(颜色、轮胎数),描述事物其实就是在描述事物的属性和行为;
属性对应是类中的变量,行为对应的类中的函数(方法)
其实定义类,就是描述事物,就是定义属性和行为,属性和行为共同称为类中的成员变量和成员方法(函数)

4.成员变量和局部变量的区别:
   (1).成员变量定义在类中,整个类中都可以访问。
        局部变量定义在函数,语句,局部代码块中,只在所属的区域有效。
   (2).成员变量存在于堆内存的对象中。
        局部变量存在于栈内存的方法中。
   (3).成员变量随着对象的创建而存在,随着对象的消失而消失。
       局部变量随着所属区域的执行而存在,随着所属区域的结束而释放。

   (4).成员变量都有默认初始化值。
        局部变量没有默认初始化值。

举例:

public class Car {//描述颜色String color = "红色";//描述轮胎数int num = 4; //运行行为void run() {System.out.println(color+"...."+num);}public static void main(String[] args){//生产汽车,在java中通过new操作符来完成;//其实就是在堆内存产生一个实体Car c = new Car();//c就是一个类类型变量类类型变量指向 对象//将已有的车的颜色改成蓝色,指挥该对象来做,在java中指挥//方式是:对象.对象成员c.color= "blue";c.run();new Car().run();/* 匿名对象(一次性使用)调用属性没意义;1.匿名对象使用方式一:当对对象的方法只调用一次时,可以用匿名对象来完成,这样写比较简化,如果对一个对象进行多个成员调用,必须给这个对象起个名字。2.匿名对象使用方式二:可以将匿名对象作为实际参数进行传递;*///需求:汽车装配厂,对汽车进行改造,将来的车能够改成黑车,//三个轮胎show(new Car());}public  static void show(Car c) {c.num = 3;c.color ="black";c.run();}}</span></span></span>

二、对象的封装

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

2.好处:将变化隔离
           便于使用;
           提高重用性
           提高安全性
3.封装原则:
   (1)将不需要对外提供的内容都隐藏起来
   (2)把属性都隐藏,提供公共访问方法对其访问;

4.封装的表现形式举例

   如private:私有权限修饰符:用于修饰类中的成员(成员变量,成员函数),私有只在本类中有效;
   注意:内存的分析,对于set方法的分析;

三、构造函数

1.构造函数的作用:可以用于给对象进行初始化
   对象一建立,就会调用与之对应的构造函数;
2.构造函数小细节:
   (1)当一个类中没有定义构造函数时,那么系统会默认给该类加入一个空参数的构造函数;

   (2)当在类中自定义了构造函数后,默认的构造函数就没有了

3.构造函数与一般函数不同

    (1)在写法上有不同

    (2) 在运行上不同;
         a.构造函数是在对象一建立就运行,给对象初始化;
            而一般函数是对象调用时才执行,给是对象添加对象具备的功能;

         b.一个对象建立,构造函数只运行一次;
            而一般方法可以被该对象调用多次;

4.什么时候定义构造函数?
  分析事物时,该事物存在具备一些特性或行为,那么将这些内容定义在构造函数中;

5.构造代码块:
   作用:给对象进行初始化;
   对象一建立就运行,而且优先于构造函数执行;
   和构造函数的区别:
   构造代码块是给所有对象进行统一初始化;
   而构造函数是给对应的对象初始化;

   注意:构造代码块中定义的是不同对象共性的初始化内容。

四、this关键字

 1 .对this的简单认识:

     this.看上去,是用于区别局部变量和成员变量同名情况
     this为什么可以解决这个问题;
     this到底代表的是什么?
     this代表它所在函数所属对象的引用;
     简单说,那个对象在调用this所在的函数,this就代表哪个对象

2.this的应用:

   (1)当定义类中功能(函数)时,该函数内部要用到调用该函数的对象时,这是用this来表示这个对象;
   但凡本类功能内部调用本类对象时,就用this,一般省略不写
   (2)this语句:用于构造函数之间互相调用;
   this语句只能定义在构造函数的第一行,因为初始化要先执行;

 

五、static的用法
1.用法:

(1).是一个修饰符,用于修饰成员(成员变量,成员函数);

(2).当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以被类名调用 类名.静态成员

2.特点:
(1).随着类的加载而加载,随着类的消失而消失,说明它的生命周期最长
(2).优先于对象存在;
明确一点:静态是先存在,对象是后存在的;
(3).被所有对象所共享;
(4).可以直接被类名所调用;

3.什么时候使用static?
要从两方面入手:
(1).当成员变量的数据各个对象都相同时,可以用static修饰,让多个对象共享。
(2).函数如果访问了特有数据(非静态成员变量),该函数是非静态的。
     函数如果没有访问特有数据,那么该函数就可以静态修饰。
     如果类中的功能都是静态的,那么该类创建对象是没有意义的,所以构造函数需要私有化。
     因为静态修饰的内容有成员变量和函数;
什么时候定义静态变量(类变量)呢?
当对象的出现共享数据时,该数据被静态所修饰;
对象中的特有数据要定义成非静态存在于堆内存中

什么时候用?
看是否被多个对象使用,static比较耗内存;不建议大量使用;

4.静态使用注意事项:
(1).静态方法只能访问静态成员,非静态方法既可以可以访问静态也可以访问非静态;
(2).静态方法不可以定义this,super关键字
     因为静态优先与对象存在,所以静态方法中不可以出现this

5.静态有利有弊:
利:对对象的共享数据进行单独空间的存储,节省空间,没有必要每一个对象中都存储一份,可以直接被类名调用。
弊端:生命周期过长,访问出现局限性;静态虽好,只能访问静态;六、实例变量和类变量

1.区别:
   (1).存放位置;
   类变量随着类的加载而存在于方法区中;
   实例变量随着对象的建立而存在于堆内存中;
   (2).生命周期:
   类变量生命周期最长,随着类的消失而消失;
   实例变量生命周期随着对象的消失而消失;
   (3).主函数是静态的;

七、主函数:是一个特殊的函数,作为程序的入口,可以被jvm调用;
1.主函数的定义:
   public代表者该函数访问权限是最大的;
   static:代表主函数随着类的加载就已经存在了
   void:主函数没有具体的返回值;
   main:不是关键字;但是是一个特殊的单词,可以被jvm识别;
   函数的参数:(String[] arg)函数的参数,参数类型是一个数组,该数组的元素师字符串,字符串类型的数组;

   主函数是固定格式的,jvm识别;
   jvm在调用主函数时,传入的是new String[0]
2.什么时候定义静态函数?
   当功能内部没有访问到非静态数据(对象的特有数据)
   那么该功能可以定义成静态的;

3.代码块。

(1).局部代码快。
   对局部变量的生命周期进行控制。
(2).构造代码块。
   对所有对象进行初始化。
(3).静态代码块。
   对类进行初始化。
静态代码块:
格式:
static {
 静态代码块的执行语句;
}

特点:随着类的加载而执行,只执行一次;用于给类进行初始化的;

八、单例设计模式:
1解决的问题:保证类在内存的对象唯一性。

想要保证对象唯一:
1.为了避免其他程序过多建立该类对象,先禁止其他程序建立该类对象
2.还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象;
3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式;
代码体现:
1.将构造函数私有化;
2.在类中创建一个本类对象;
3.提供一个方法可以获取到该对象;

 对于事物该怎么描述,还怎么描述。
当需要将该事物的对象保证在内存中唯一时,就将以上三步加上即可。

class Single {private Single(){}private static Single s = new Single();public static Single getInstance() {return s;}}public class SingleDemo {public static void main(String[] args) {Single s = Single.getInstance();System.out.println(s);}}</span>


2.两种方式的区别?
1.饿汉式:
single类一进内,就已经创建好了对象

public class Single {private static Single s = new Single();private Single() {}public static Single getInstance() {return s;}}</span>
2.懒汉式(延迟加载方式):对象是方法被调用时,才初始化,也叫做对象的延时加载;
single类进内存,对象还没有存在,只有调用getIstance方法时,才建立对象;

package day01;class Single {private static Single s = null;private Single() {}public static Single getInstance() {if(s==null) s = new Single();return s;}}

开发时用饿汉式;

一、继承

1.意思:当多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再重复定义这些属性和行为,只要继那个类即可。

2.举例:将学生和工人的共性的内容抽取出来,单独进行描述;
             只要让学生和工人与单独描述的这个类有关系就可以了

3.特点:

(1).提高了代码的复用性;
(2).让类与类之间产生了关系,有了这个关系,才有了多态的特性;
注意:继承是所属关系;不要乱继承;千万不要为了获取其他类的功能,简化代码而继承;必须是类与类占有所属关系才可以继承,所属关系is a;

4.应用

如何使用一个继承体系中的功能;
想要使用体系,先查阅体系父类的描述,因为父类中定义的是该体系中共性功能。那么这个体系已经可以基本使用;
那么在具体调用时,要创建最子类的对象,为什么呢:
一是因为有可能父类不能创建对象,
二是创建子类对象可以使用更多的功能,包括基本的也包括特有的;
简单一句话:查阅父类功能,创建子类对象使用功能;

举例:

 

//将学生和工人的共性的内容抽取出来,单独描述成一个类,只要他们继承这个类就可以了,提高代码的复用性class Person{//共同属性String name;int age;//person类对象初始化Person(String name,int age){this.name=name;this.age=age;}}class Student extends Person{//student对象初始化Student(String name,int age){super(name,age);}//子类特有行为void study(){System.out.println("good study");}class Worker extends Person{//worker对象初始化Worker(String name,int age){super(name,age);}//子类特有行为void work(){System.out.println("good work");}}}public class ExtendsDemo {public static void main(String[] args) {Student s = new Student("lisi",20);s.study();}}

5.子父类出现后,类成员的特点:
  类中成员:
  a.变量;
  b.函数;
  c.构造函数;

(1).变量:
如果子类中出现非私有的同名变量时,子类要访问本类中的变量,用this,子类要访问父类中的同名变量,用super;

super是的使用和this的使用几乎一致;
this代表的是本类对象的引用。
super代表的是父类对象的引用;

(2).子类中的函数
当子类出现和父类一模一样的函数时,
当子类对象使用函数,会运行子类函数的内容。
如同父类的函数被覆盖一样。

这种情况是函数的另一个特性:重写(覆盖)

当子类继承父类,沿袭了父类的功能,到子类中,但是子类虽具备该功能,但是功能的内容却和父类不一致,这时,没有必要定义新功能,而是使用覆盖特殊,保留父类的功能定义,并重写功能内容;

(3)覆盖:
a.子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败;
b静态只能覆盖静态;

记住:
重载:只看同名函数的参数列表;
重写:子父类方法要一模一样,包括返回值类型;(在多态中返回值子父类可以不一样,后面再说;)

(4).子父类中的构造函数
在对子类对象进行初始化时,父类的构造函数也会运行,那是因为子类的构造函数默认第一行有一条隐式的语句super();
super()会访问父类中空参数的构造函数,而且子类中所有的构造函数默认第一行都是super();

 注意:为什么子类一定要访问父类中的构造函数。
因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的;
所以子类在对象初始化时,要先访问一下父类中的构造函数;

注意:为什么完成这个必须的动作,就在子类的构造函数中加入了super()语句?
如果父类中没有定义空参数构造函数,那么子类的构造函数必须用super明确要调用父类中哪个构造函数。同时子类构造函数中如果使用this调用了本类构造函数时,那么super就没有了,因为super和this都只能定义第一行。所以只能有一个。
但是可以保证的是,子类中肯定会有其他的构造函数访问父类的构造函数。

注意:super语句一定定义在子类构造函数的第一行;


6.子类的实例化过程:
结论:
子类的所有构造函数,默认都会访问父类中空参数的构造函数;因为子类每一个构造函数内的第一行都有一句隐式super();

当父类中没有空参数的构造函数时,子类必须手动通过super或this语句形式来指定要访问父类的构造函数;

当然,子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。子类中至少会有一个构造函数会访问父类中的构造函数。


父类中构造函数也有super,object是所有类的父类(上帝类);

为什么super和this不能再同一行?
因为他们都只能写在第一行,
为什么写在第一行?
因为初始化动作要先做;

7.final:最终。作为一个修饰符;
(1).可以修饰类,函数,变量。
(2).被final修饰的类不可以被继承。为了避免被继承,被子类复写功能。(弥补了继承打破了封装性的弊端)
(3).被final修饰的方法不可以被复写。
(4).被final修饰的变量是一个常量,只能赋值一次,既可以修饰成员变量,又可以修饰局部变量。
当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都会给这些值起个名字。方便与阅读。而这个值不需要改变,所以加上final修饰;
写法规范:常量所有字母都大写,多个单词,中间用_连接。
(5).内部类定义在类中的局部位置上,只能访问该局部被final修饰的局部变量

小想法:一个新的东西有好处,也有弊端,应尽量利用好处,减少弊端;

8.一个对象实例化过程:
Person p = new Person();
(1)JVM会读取指定的路径下的Person.class文件,并加载进内存,
并会先加载Person的父类(如果有直接的父类的情况下).
(2)在堆内存中的开辟空间,分配地址。
(3)并在对象空间中,对对象中的属性进行默认初始化。
(4)调用对应的构造函数进行初始化。
(5)在构造函数中,第一行会先到调用父类中构造函数进行初始化。
(6)父类初始化完毕后,在对子类的属性进行显示初始化。
(7)在进行子类构造函数的特定初始化。
(8)初始化完毕后,将地址值赋值给引用变量.

二、抽象类

1.定义:当多个类中出现相同功能,但是功能主体不同;这时可以进行向上抽取。这时,只抽取功能定义,而不抽取功能主体;
抽象:看不懂,模糊的,不具体的,不能创建一个看不懂的类的对象,因为调用方法没意义,如果方法加上括号就可以了;
2.抽象类的特点:
(1).抽象方法一定在抽象类中;
(2).抽象方法和抽象类都必须被abstract关键字修饰;
(3).抽象类不可以用new创建对象,因为调用抽象方法没意义;
(4).抽象类中的方法要被使用,必须由子类复写起所有的抽象方法后,建立子类对象调用;如果只覆盖部分抽象方法,那么该子类还是一个抽象类;(抽象类的抽取是分析问题来的,不是单纯抽取代码)
注意:抽象类可以强制子类做一些事情;
抽象类和一般类没有太大的不同,该怎么样描述事物,就如何描述事物;只不过该事物中,出现了一些看不懂的东西,这些不确定的部分,也是该事物的功能,需要明确出来,但是无法定义主体;
通过抽象方法来表示。凡是不确定的,沿袭到子类来确定;

抽象类比一般方法多了个抽象函数,就是在类中可以定义抽象方法;
抽象类不可以实例化;

特殊:抽象类中也可以不定义抽象方法,这样做仅仅是不让该类建立对象;

3.抽象类举例:
假如我们在开发一个系统时,需要对员工进行建模,员工包含3个属性;姓名、工号、及工资。经理也是员工,除了含有员工的属性外,另外还有一个奖金属性,请使用继承的思想设计出员工类和经理类。要求类中提供必要的方法进行属性访问;

员工类:name id pay
经理类:继承了员工,并有自己的bonus。
抽象类就是对某一些事物描述的时候,有些地方描述不具体,描述不了。

package day02;abstract class Employee{//定义变量;private String name;private String id;private double pay;//初始化;Employee(String name,String id,double pay) {this.name = name;this.id = id;this.pay = pay;}//行为public abstract void work();//强制子类必须工作,但工作具体内容以具体情况为准;}class Manager extends Employee{private int bonus;Manager(String name,String id,double pay,int bonus){super(name,id,pay);this.bonus = bonus;}// 子类自己的工作方式public void work() {System.out.println("manager work");}}public class AbstractDemo {public static void main(String[] args) {new Manager("lisi", "101", 2000, 500).work();}}

4.模板方法模式
需求:获取一段程序运行的时间。
原理:获取程序开始和结束的时间并相减;

获取时间:System.currentTimeMillis();

当代码完成优化后,就可以解决这类问题;这种方式模板方法设计模式;

什么是模板方法呢:
在定义功能时,功能的一部分是确定的,但是有一部分是不确定,而确定的部分在使用不确定的部分;那么这时就将不确定的部分暴露出去,由该类的子类去完成;

class GetTime(0 {//final关键字不让子类覆盖;public final getTime(){long start = System.currentIimeMillis();runCode();long end = System.currentIimeMillis();System.out.print("毫秒:"+(end-start));}public abstract void runCode();}class SubTime extends GetIime {public void runCode(){for(int i=0;i<10000;i++){System.out.println(i);}}}class TemplateDemo{public static void main(String[] args){SubTime gt = new SubTime();gt.getTime();}}


三、接口

1.接口:初期理解;可以认为是一个特殊的抽象类,当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示;
class用于定义类
interface用于定义接口;

2.接口常见定义格式特点:
(1).接口中常见定义:常量,抽象方法。
(2).接口中的成员都有固定修饰符;
常量:public static final
方法:public abstract
记住:接口中的成员都是public的;

接口:是不可以创建对象的,因为有抽象方法;
需要被子类实现,子类对接口中的抽象方法全部覆盖后,子类才可以实例化;否则子类是一个抽象类;

接口中子类与父类的修饰权限必须相同,而抽象类中可以不相同;

接口可以被类多实现,也是对多继承不支持的转化形式;

类与类之间是继承关系,类与接口直接是实现关系。接口之间是继承关系;

3.接口的特点:
(1).接口是对外暴露的规则;
(2).接口是程序的功能扩展;
(3).接口可以多实现;
(4).类与类之间是继承关系,类与接口直接是实现关系,类可以在继承一个类的同时实现多个接口,接口之间是继承关系(java支持多继承,只有在接口中体现,类中是通过接口的实现);

4.抽象类和接口的异同点:
相同点:
都是不断向上抽取而来的。
不同点:
(1)抽象类需要被继承,而且只能单继承。
接口需要被实现,而且可以多实现。
(2)抽象类中可以定义抽象方法和非抽象方法,子类继承后,可以直接使用非抽象方法。
接口中只能定义抽象方法,必须由子类去实现。
(3)抽象类的继承,是is a关系,在定义该体系的基本共性内容。
接口的实现是 like a 关系,在定义体系额外功能。

举例:
abstract class Sporter
{
abstract void play();//抽象类基本功能
}

interface Study//接口额外功能;
{

}
class wangwu extends Sporter implentments Study
{

}

package day02;//抽象学生类abstract class College{//学生肯定都学习和睡觉,但吸烟就不是必须的,只是额外的//抽象的学习方法abstract void study();//非抽象的睡觉方法void sleep(){System.out.println("sleep");}}//接口interface Smoking{void smoke();//定义额外的功能}//lisi有吸烟的嗜好,,但也要学习,实现吸烟接口class Lisi extends College implements Smoking{//复写学习方法void study(){System.out.println("Lisi_study");}//复写吸烟方法public void smoke(){System.out.println("Lisi_smoking");}}//mike是好学生,不吸烟class Mike extends College {//复写学习方法void study(){System.out.println("Mike_study");}}class InterfaceDemo{public static void main(String[] args) {Lisi l = new Lisi();l.study();l.smoke();new Mike().study();}}

5.模板方法模式
需求:获取一段程序运行的时间。
原理:获取程序开始和结束的时间并相减;

获取时间:System.currentTimeMillis();

当代码完成优化后,就可以解决这类问题;这种方式模板方法设计模式;

什么是模板方法呢:
在定义功能时,功能的一部分是确定的,但是有一部分是不确定,而确定的部分在使用不确定的部分;那么这时就将不确定的部分暴露出去,由该类的子类去完成;


 


 

package day02;abstract class GetTime{//final关键字不让子类覆盖;public final void getTime(){long start = System.currentTimeMillis();//开始时间runCode();long end = System.currentTimeMillis();//结束时间System.out.print("毫秒:"+(end-start));}public abstract void runCode();//程序代码是不确定的部分,提供抽象方法}class SubTime extends GetTime {//重写抽象方法public void runCode(){for(int i=0;i<10000;i++){System.out.println(i);}}}public class TemplateDemo{public static void main(String[] args){SubTime gt = new SubTime();gt.getTime();}}


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0 0
原创粉丝点击