(2)- 面向对象(图)

来源:互联网 发布:企业数据库er图 编辑:程序博客网 时间:2024/05/24 07:44
---------------------- ASP.Net+Android+IO开发S、.Net培训、期待与您交流! ----------------------


个人学习后归纳的知识点,利于整体记忆。

1、 面向对象的概述

面向对象其实是一种思维方式,帮助人们更好的对现实世界进行抽象和建模。这种思维用在程序设计上,是为了给待解决问题提供一个合适并可扩展的解决方案。面向对象的核心就是对象的建立,将问题中的事或物抽象成一个个对象,从对象的角度去考虑它的行为和这些对象间的关系,而不是从过程。通过这些对象间的共性,扩展等关系进一步抽象或封装成类,类相当于一类事物的描述集,它有着封装、继承和多态的特性。

对于面向对象的论述很多,不过最终都是为了解决问题需求的,只是这样的思维方式能然我们更好、更快、更简单的建立问题的解决方案或模型。


2、 面向对象的举例

为了更好理解面向对象的思想,我们通过一些实例来理解,首先要明确问题中某个行为或功能是谁发出的,这里记住:谁对这个行为负责或谁拥有这个行为的数据,谁就能发出或提供这个行为

如:

(1)   人开门

       行为:开。

       分析:打开门,这件事真正能执行的是门,门拥有门轴,它负责开这个行为。人是命令的发出者,即指挥者。

(2)   人在黑板上画圈

       命令者:人,发出画圈的命令。

      执行者:圆,圆的基本信息(圆心,半径)都在圆上,圆负责画。

      分析:圆对象的构造比较抽象,这便是面向对象思维所要体现的,圆被定义时就拥有圆心和半径,才能画出圆来。若画的行为是人,而人没有这两个属性,人空有画的行为也是构造不出圆的,所以画的行为应该是圆来负责的,黑板属载体。


3、 类的三大特性:封装、继承、多态

(1)   封装性

封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。有点像插座,电路细节都在壳里,只带几个孔,提供给插头。

好处:将变化隔离,便于使用,提高重用性,提高安全性。这些好处都可以从一个插座上体会,比如把三孔插座的接地线剪掉,但这样的变化依旧不影响三孔插头对象。

 

访问权限的修饰符:public,protected,private和默认(default),他们都是控制外部对封装后的类或成员进行访问的权限,是封装的一种表现形式。如果在修饰的元素上没有写任何修饰符,则代表默认。

下表格分别描述了这几个修饰符的访问能力:

作用域(能力)

当前类(本类)

包(package)内

子孙类

各包间

public

protected

×

default

×

×

private

×

×

×

可见访问能力由上至下减小,只要记住4种访问权限,4种访问能力,再以递减的顺序就很容易画出上面的表。

(2)   继承

什么是继承:一个对象可以使用另一对象的非私有的属性和方法。前者称子类,后者称父类。


单继承:java中只支持单继承,简单的说一个子类不能有两个父亲类,但是一个父亲类可以有多个子类。

如:有A、B、C三个类,代码class Aexdents B,C{}就是不允许的,A同时继承了B,C,违背单继承原则。


以下都是可行的:

class C//一个C类可以有多个子类如A,B{}class B extends C{}class A extends C{}

另外也可以这样:这也叫多层继承,不是叫多继承哦。

//若A是子类,C可以做为父类的父类,也就是爷爷类存在,//因为A的对象是可以调用C的方法的,这也叫多层继承,不是多继承哦。class C//爷爷类{    public void cc(){}}class B extends C//父类{
    public void bb(){}
}class A extendsB//子类{ //public void cc(){}//还可复写C的方法。}public class Test{ public static void main(String[] args) { A a = new A(); a.cc();//调用C的方法 }}

1)子类覆盖父类方法时需注意:

(a)除修饰符,方法名及参数都要一模一样

(b)子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。如

父类定义方法:

void show(){}

public void look(){}

子类覆盖成:

private show(){}

void look(){}

这样的覆盖都是错误的。

(c)静态只能覆盖静态,因类的创建时期早于对象。

(d)重载与复写的区别 

重载:只看同名函数的参数列表变化。

复写:除修饰符,同名函数所有要一模一样。

 

2)继承的好处:提高了代码的重用性;为多态的出现提供了前提。


3)注意点:

子类中所有的构造函数都会默认调用父类的空参数的构造函数,即每一个子类构造函数内的第一行都有默认的调用语句super()。

如果父类中没有空参数的构造函数,那么子类在构造函数中,必须通过super指定访问一个父类中一个带参的构造函数。

如果子类构造函数中用this()来指定调用子类自己的构造函数,那么被调用的构造函数也一样会访问父类中的构造函数。


(3)  多态

什么是多态:一般对于类的方法而言,在继承的前提下,其子类对象可以有不同的表现形式,即对于同一个消息(方法)有不同或者说专属的响应(表现)。

比如:动物为父类,动物都有叫的行为,狗,猪,猫都是动物的子类,但叫的声音各不相同。


多态的前提:

①必须要有关系,比如继承、或者实现。

②通常会有覆盖操作,否则无意义。 

多态的体现:父类的引用指向了自己的子类对象。像Fu a = new Zi();

多态的好处:提高了程序的扩展性。

多态的弊端:当父类引用指向子类对象时,虽然提高了扩展性,但是只能访问父类中具备的方法,不可以访问子类中特有的方法。(一旦转型成父类对象,用的方法都要看父类有才能调用)


转型:类型提升,如动物 dw= new 猫();//类型提升,向上转型。

    可以将dw再转回来,猫 m = (猫)dw;//向下转型。这里将用猫的行为

    类型转换中始终看子类对象,是猫的转型都跟猫有关,不能转成狗。

   

类成员特点:

(a)在多态中非静态成员函数(普通函数)的特点:

在编译时期:参阅引用型变量所属的类中是否有调用的方法,有则编译成功,无则失败(静态绑定)。简单说就是看左边。

在运行时期:参阅对象所属的类中是否有调用的对象(动态绑定)。简单说就是看右边。

总结:成员函数在多态调用时,编译看左边,运行看右边。

这里也体现了上面说的多态弊端,只要转型成父类对象,就得局限于父类的方法执行了。


 (b)成员变量:无论编译或运行都参考左边(对象所属的类)。

   

 (c)静态成员方法:无论编译或运行都参考左边(对象所属的类),因前期无需考虑对象,只要有类就成。

 

以下代码体现:

class Animal{    int num = 8;    void show(){        System.out.println("我是动物!");    }    static void eat()    {        System.out.println("父类静态");    }}class Cat extends Animal{    int num = 1;    void show(){        System.out.println("我是猫!");    }    void mao()    {        System.out.println("猫叫");    }    static void eat()    {        System.out.println("子类静态");    }}class Dog extends Animal{    void show(){        System.out.println("我是狗!");    }}public class Test{    public static void main(String[] args)    {        Animal dw= new Cat();//类型提升,向上转型        dw.show();//猫的方法        Cat c = (Cat)dw;//向下转型        c.show();//猫方法               //dw.mao();//调用子类特有方法mao(),但失败,证明上述多态的弊端,转型成父类,得用父类有的方法。               //结果为8,体现了成员变量取值,看左边对象所属类。        System.out.println(dw.num);               //输出是“父类静态”,体现了静态方法的调用,看左边对象所属类来决定        dw.eat();         //运行出错,不能将猫转成狗,转型中得看子类对象决定        /*Dog d = (Dog)dw;        d.show();*/               //运行出错,不能将纯粹的(无转型)父类对像转成子类类型        /*Animal al = new Animal();        Cat cc = (Cat)al;        cc.show();*/    }}


4、  代码块(构造代码块、静态代码块)

构造代码块:

作用:给对象初始化的。

对象一建立就运行,优先于构造函数。

与构造函数的区别:构造函数是给所有对象就行统一初始化,而构造函数是给对应的某个对象初始化。

 

静态代码块:随着类的加载而执行,只执行一次,并优先于主函数。

     作用:给类进行初始化。

//在子父类中,构造代码块,静态代码块,构造函数的执行顺序:class A{       A(){            System.out.println("....父类,构造函数!");          }       static {            System.out.println("静态,父类代码块!");       }       {            System.out.println("非静态,父类,构造代码块!");       }}class B extends A{      B(){           System.out.println("....子类,构造函数!");         }      static {           System.out.println("静态,子类代码块!");         }                  {            System.out.println("非静态,子类,构造代码块!");         }} public class Test{     public static voidmain(String[] args){     new B();}      }/*输出结果:静态,父类代码块!静态,子类代码块!非静态,父类,构造代码块!....父类,构造函数!非静态,子类,构造代码块!....子类,构造函数!可见:执行顺序,静态代码块是由父到子,再到非静态时,要完成父类的构造函数,再跳到子类。这个也可以看出,先加载子和父类初始化的代码,在分别考虑子和父类对象的初始化的代码,类优先于对像。 */


5、 类和对象的关系

类:对现实世界某一类事物的抽象描述,如动物。


对象:就是类描述的那一类事物中的某个个体,实实在在的存在个体,如猪,虎。


(1)如何构造出一个类呢?

从一类事物(或说对象)中抽象或提取出它们共有的内容,如属性和行为,而对象就是类的一个实例化。

在程序设计中,类相当于一种车的设计蓝图,是用来描述和设计过程中用的,不能拿来当交通工具。对象就相当于一辆设计出来的车,是可以拿来开的,但是这样的车可以有很多辆,即很多对象。

 

(2)Object类:在java中所有类都继承Object类。它含的方法是所有类都具有的,如常用的equals(Object obj)比较其他某个对象是否与此对象相等。

 

(3)对象的初始化过程:

Person p=new Person("张三",20);这条语句做了什么?

(a)因为new用到了Person.class,所以会先找到Person.class文件并加载到内存中。

(b)执行该内存中的static代码块,如果有的话,给Person.class类进行初始化

(c)在堆内存中开辟空间,分配内存地址。

(d)在堆内存中建立对象的特有属性,并进行默认初始化。

(e)对属性进行显示初始化。

(f)对对象进行构造代码块初始化。

(g)对对象进行相应的构造函数初始化。

(h)将内存地址赋给栈内存中的p变量。

 

(4)匿名对象:

匿名,即没有引用变量接收的声明对象。一个对象只使用一次时就可用匿名对象简化书写,也可做函数的实参传递。

如 new 类名();和void metho(new类名()){}语句都是匿名对象。

匿名对象使用后,Java会对一定时间内无引用的对象的内存进行清理。


6、  this,super,static在类中的作用

this:表本类对象,this.xxx表本类对象调用。可以区分局部和成员变量同名的情况。

           this(有参或无参);表示调用本类的构造函数。要求放在构造函数内的第一句。


super:类似this,在有继承关系的子类中表示父类引用。

              super(有参或无参)表示调用父类的构造函数,要求放在子类构造函数的第一句。


static:作用修饰符,修饰成员(变量、方法),只能修饰成员。被修饰后,成员将不在堆内存中,类的对象共用。不仅能被对象调用还能被类名调用。


final在基础篇有说,不赘述了。        

类中全部都是静态成员的类可以作为工具类。

      

  注意:静态方法只能访问静态成员。而非静态方法可以访问静态成员。

              静态方法中不能使用this,因为静态优先于对象存在。


---------------------- ASP.Net+Android+IO开发S、.Net培训、期待与您交流! ----------------------

原创粉丝点击