Lantian和Tianqi的移动开发之旅 - 003 OOP

来源:互联网 发布:软件维护不能用 编辑:程序博客网 时间:2024/05/01 14:43
1.面向对象程序设计的基本概念
面向对象程序设计 - OOP程序设计模式
将程序看成是一系列的对象组成的,而非一些列的动作组成的,对象是程序设计的基本单元
对象:包含状态(数据)和行为(状态)的程序设计实体 - 类的实例化
状态:我们将保存在对象中的保存对象的信息称之为状态
行为:一些对象可以完成的动作,常常有"报告"和"修改"状态
首先我们需要明确的是,对象本省并不能构成完整的程序,对象之时具有不同角色和功能的程序组件,对象可以作为解决更为复杂的程序设计的一部分,创建并适用对象的代码称之为客户
客户:与该类和该类的对象进行交互的代码

eg讲解:Point(Java.awt包)
状态:横坐标,纵坐标(整数)
行为:syso - Point 打印坐标
      translate(x,y)移动x,y距离
          public:我们话可以直接对横坐标和纵坐标进行操作
      setLocation(x,y)设置坐标值
      distance(Point X)计算该点到x的距离,并返回
对象的状态:
           只包含信息没有行为的我们也可以叫他结构体
对象的行为:
对象中类的方法,用来操作类中(对象中的)数据元素,这里我们要小心对数据元素进行操作的时候有作用域的问题,因为我们的变量定义是在数据的操作的作用于是定义在第一个大括号之内的,对于类的数据元素来说也是一样的,类中的状态数据元素的作用于就是整个类
隐含的参数:
市里的方法可以通过摸个隐蔽的渠道来指导我们当前操作的对象(隐含参数,我们调用的时候就知道我们的示例函数操作的对象),每个对象都有自己的行为函数的副本
修改器+访问器:
前者修改对象的内存信息,后置不做任何修改,我们只是访问我们的对象的内存数据


toString方法:Java语言的设计者认为Java应当与String类型良好的配合工作,在syso中我们已经可以对字符串直接进行拼接操作
当Java需要我们利用syso标准输出一段字符串或者实现字符串的连接操作的时候,会自动调用相应的字符串toString方法,返回的是表示对象实例的字符串,toString方法不存在调用的参数,但是返回一个字符串
但是一旦加入我们要输出的东西并不存在相应的toString方法的话,Java会自动在类的名称后面添加一个@之后跟上一段的乱码(通常和你存的地址有关),但是一旦我们定义了相关的toString方法的话,我们实惠自定调用的自己的toString方法
建议位字节写的每一个类都加上toString方法


对象的初始化 - 构造函数:
构造函数用public修饰,后面是雷鸣和我们所需要的参数,构造函数也是针对摸一个特定的对象,函数的名字和类的名字是相同的,并且构造函数没有返回值
我们经常说的new操作的实质:
1.创建新的对象,并未对象开辟相应的内存区域
2.对对象调用相应的显示构造函数
3.在站区域中我们创建相应的对象的引用变量,并将我们新开辟的UI想的内存地址分配到我们到我们的引用变量上
如果我们没有定义构造函数的话,其实是并不会出现错误的,因为Java自动为没有显示设定构造函数的类设定缺省 默认的构造函数
但是缺省的构造函数会自动的将为类中的相应的状态变量设定0和相应的空值


关键字this:
在类的内部我们可以访问到相应的隐含参数,注意this只有一个内存区域,当我们制定不同的对象的时候,我们的this是指向不同的对象的,该方法一个重要的作用就是避免函数的名字的重复
构造函数的重载:一个类是允许存在多个不同的构造函数的,为了方便我们在建立对象的时候的多重的情况的选择




封装性:
封装的概念:讲一个对象的内部事项的方法隐藏起来,不让他的客户代码看到
抽象:我么只关注问题的本身属性而不关注我们的内存的实现的细节
抽象是封装的表现,二良好的封装也是我们设计需要的

私有成员:
我们需要对垒中的成员进行封装的话,我们至少要在状态的开头用private关键字声明其为私有的属性
私有的变量对于类内部的代码来说是可见的,但是对于我们的外部的客户代码来说是不可见的
我们为了可以读取对象的相应的状态可以增设set或者get方法,目的是返回一个类内部成员的副本,相当于我们对外部的客户代码只有访问权限,没有修改的权限



类的不变式:在类的对象的生命周期之内,我们对于一个状态的永真断言




2.继承和接口:
继承:允许我们的代码的复用,代码共享
接口:允许我们的用统一的行为取处理不同的对象,不需要这些对象之间共享代码
代码的复用:我们抽象出代码的普遍的结构之后抽象出来相同的部分从而实现的代码的重复使用
在多个程序中相同使用一段代码,我们引入集成的概念是的哦我们呢可以在一个类的基础上对类进行相应的扩充使得我们的逻辑更加的清晰
继承:
1.相同,共用
2.不同,对于不同的类我们制定不同的规范
Java允许我们通过继承的方法,避免在定义一个相似的类的时候重复的产生冗余的代码,如果已经有一个类包含了我们需要的所有的信息,我们完全可以继承这个类,共用相同的部分,至于特殊的部分我们在添加修改即可
派生出来的类叫做 - 子类,子类继承自 - 父类的全部的状态和行为
我们一般都说是子类扩展了父类,因为子类不仅可以介绍了父类的状态和行为,还可以添加自己特有的性质  ????控制子类访问的protected
在Java中,我们只是提倡单继承,一个类可以扩展成多个类,但是一个类智能是有一个父类扩展来的


关键字引入:extends


           方法的重写:咋子类中我们可以通过重写父类的函数方法改变我们的子类的行为
重写:在子类中提供给父类的默写行为的一些新的实现的函数版本,替换我们之前的父类的函数


与父类的交互:super
调用重写的方法,super关键字可以再子类中调用到父类的构造函数和方法
注意子类不能说会用父类中的私有字段,Java限制类子类直接的访问从父类继承来的字段
构造函数是不会被子类继承的,子类的够早的时候是默认我们会调用父类的狗在函数的,如果我们没有制定相应的构造函数说明,我们编译器会自动的生成一个没有参数的默认的父类的构造函数
所以说,我们我们在子类中显示调用父类的构造函数的方法就是调用我们super方法,调用父类的构造函数,并且该super语句必须在构造函数的第一行
super还允许我们调用已经被冲写的父类函数,super只会调用上次的一个父类
Object类:
Java中有一个Object类是所有的类的父类,没有extends额类,系统自动的默认添加上extends Object
Object的主要的方法:
1.clone()创建对象的副本
2.equals()判断当前对象是否相等,值
3.finalize()对象被销毁的时候自动调用
4.getClass()返回对象的类型的信息
5.hashCode()返回与对象相关的一个数字,在默写数据结构中游泳
6.toString()字符创的形式返回对象的信息
7.多线程相关的方法
如果我们希望摸个方法可以接受任何类型的对象作为参数,我们可以将形参设置为Object,返回值是Object也是合法的,使用的时候记住先强制类型转换


equals()方法:
==运算符不能用在对象的身上,因为对于不同的对象也可能具有相同的内容
==表示我们判断两个被比较的引用是否引用了相同的对象,而不是比较我们的要比较的引用对象的对象的状态是否是相同的
equals()方法不一样,equals()方法比较两个对象的状态是否是相同的(比较我们的两个变量的内容是否相同),如果我们没有对equals()方法进行重载的话,那么equals()方法实际上就是==,只有我们自己重写这个这个方法才会有用处


instanceof关键字:注意,如果我们使用通用的Object来进行比较,我们只是将当前的对象的引用类型表示成父亲级别的变量,但是我们instanceof比较的时候还是使用原来的对象的本身来进行比较
instanceof关键字用来判断检测一个变量是否是某个类型的对象,返回值是boolean类型
eg:如果是同一个类型的我们就先强制类型转换然后进行某种操作,不是的话我们就返回一个false的boolean
public boolean equals(Object x)
{
if(x instancof point) x=(point)x,return 判断;   *****instanceof判断当前的引用变量指向什么类型的对象*****
else return false;
                       }
上面的代码是大多数的equals函数的判断的副本,我们可以当做模板来记忆


多态性:继承的好处就是我们通过继承实现了代码的复用,就像我们上面对于继承中的方法重写中哪里说的一样,我们在大量的一批的数组中同时保存一个继承链中的类的对象的时候,因为不同的集成的子类对于相同的父类函数进行了重写
        所以说我们可以在不同的对象中调用相同的函数来实现不同的行为反应,我们成这种代码的能力叫做多态
定义:允许一段代码作用于几种不同的类型的对象中,而且代码会根据对象的不同自动的执行相应的不用的动作
在C++中,我们通过父类的指针指向不同的子类的对象从而实现调用不同的子类中的相同的方法实现不同的动作
在Java中,我们已经没有了指针的概念,但是我们还是有引用的概念,我们的引用可以指向不同的对象,从而实现和上述一样的效果
/*eg:
public class class_in_java {


public static void test(Object x)
{
x=(data)x;
System.out.println(x);
System.out.println('\n');
}
public static Object test2(data x)
{
return x;
}
public static void main(String[] args) {
// TODO 自动生成的方法存根
//data a=new data(1,2);
//test(a);
//System.out.println((data)test2(a));
data a=new data(1,2);
System.out.println(a);
//a.change()   这里的调用就是错的
a=new pdata(2,2);
System.out.println(a);
}


}


class data
{
protected int a;
protected int b;
public data(int x,int y)
{
a=x;
b=y;
}
public String toString()
{
return Integer.toString(a)+Integer.toString(b);
}
}


class pdata extends data
{
public pdata(int x,int y)
{
super(x,y);
}
public void change()
           {
syso - 输出
           }


public String toString()
{
return Integer.toString(a*b);
}
}/*
**************多态的基础就是引用型变量(Java)没有必要和所引用的对象的类型完全匹配,这是最重要的************
**************我们确切的来说,一开始我们声明城市父类的引用类型我们完全之后可以用来直接指向子类的对象示例*********这一点同C++
在基本数据类型的时候我们知道我们可以将精度小的数据类型强制转化成精度高的数据类型,但是在Java的对象的中,我们用父类(精度低的结构)的引用指向子类的对象(精度高的结构)的时候,不会发生强制转化
但是确实,我们这是后的变量的类型是父类,大师指向确实是子类,用instanceof完全可以验证
 
一个多态的经典的例子就是,我们可以将父类类型的引用作为函数的参数或者返回值,这时候,我们虽然我们结果是父类类型的引用变量,但是实际上我们指向的对象是动态的,是不同的
也正因为我们的子类都重写了父类的方法,所以说我们完全可以用一段相同的代码实现不同的动作,这就是多态的核心本质


但是有一个注意点,我们的父类的引用类型如果引用的是子类的对象的时候,我们只可以调用父类的已知的方法,不能直接调用出子类的方法(虽然这时候对象确实是子类)
/*eg:
public class class_in_java {


public static void test(Object x)
{
x=(data)x;
System.out.println(x);
System.out.println('\n');
}
public static Object test2(data x)
{
return x;
}
public static void main(String[] args) {
// TODO 自动生成的方法存根
//data a=new data(1,2);
//test(a);
//System.out.println((data)test2(a));
data a=new data(1,2);
System.out.println(a);
//a.change()   这里的调用就是错的
a=new pdata(2,2);
System.out.println(a);
}


}


class data
{
protected int a;
protected int b;
public data(int x,int y)
{
a=x;
b=y;
}
public String toString()
{
return Integer.toString(a)+Integer.toString(b);
}
}


class pdata extends data
{
public pdata(int x,int y)
{
super(x,y);
}
public void change()
           {
syso - 输出
           }


public String toString()
{
return Integer.toString(a*b);
}
}/* 因为这个时候我们编译器是只看父类的引用的,默认父类没有子类独有的方法
一句话,我们的多态性中,父类只能调用被重写的方法,但是父类引用不能直接调用子类的独有的方法
解决这种问题我们可以通过对象之间的强制类型转换来实现,但是我们必须要保证强制转换的两个对象的之间实在同一颗继承树上的,否则我们会造成运行时错误


在继承的时候我们非常要注意OOP的可替换性,在面向对象的程序过程当中,我们必须要明确所有的包括equals()等方法都会有对称的性质,造成这种现象出现的原因是我们的错误的继承的滥用导致向下和向上转型的部队称,父类引用的instanceof识别子类,但是子类的instanceof不识别父类
为了避免继承的麻烦的问题,我们可以使用组合类的思路来实现,没有了继承的向上向下转型造成的麻烦了




接口:interface关键字引用就好
Java的局限性显而易见,Java只支持单继承,一个类智能从一个父类继承而来,Java为了弥补这样的缺陷,使用了接口这个性质,我们可以用接口作为多各类的共同父类型,而且不会涉及代码共享
接口定义:某些类承诺会实现一组方法(注意是方法),这样的话我们可以用类似的代码来处理这些类


接口和类很类似,但是接口之表示方法的声明,不包括方法的实现,一个类承诺实现某一个接口,说明该类会实现接口中声明的那些方法,从而实现了多继承,结合多态的特性,我们完全可以通过上面描述的多态的特性去处理所有的实现了该接口的代码
当我们不需要共享代码的时候,我们就用借口来实现相应的过程


抽象方法:一个只具有声明但是没有实现的行为,当一个类实现一个抽象方法的
接口的抽象的特性代表接口不能被实例化




引用接口的时候我们需要用到implements关键字,一个类声明了实现了接口,那么我们在该类中就必须要实现接口的抽象方法,否则我们的编译就会不通过,多态也可以应用


接口的优点:
实现了某一个接口的一组类和具有能继承关系的一组类之剑一样都已明确的层次关系,接口充当了这些类的父类的角色,其实接口和上面的父类的堕胎一样,也可以指向子类(实现了接口的类)
接口的作用本人有自己的理解,接口是对动作的抽象,有的一些类没有集成的关系,但是他们都可以由一些相同的动作(飞机,鸟),但是我们不能让飞机和鸟都从一个类里面继承下来(这样很怪异)
所以说,对于不是一个继承树上的一些类来说,我们将的共同的行为进行抽象,我们只需要事项这些行为就可以啦,并且,我们还可以将接口的类型作为引用类型产生更广泛意义上的多态
摘引网上的一段解释:
你只要记得接口就是一个特殊的抽象类。实现它的类它必须对其所有方法进行重写。
                                                         接口是个比较抽象的东西。它一般来说可看作是1个功能扩展的类。比如你已经写好了1个类。而且也已经写好了所有的方法通俗点说就是实现了所有的功能。但现在如果又要多增加个功能。而又不想修改源代码的情况下。你就可以考虑实现接口。接口里写要增加的方法(功能)。让你这个类实现它。你就必须重写了这个方法。
/*Madai的理解是:
  java接口的用处主要体现在下面几个方面:
 
  (1)通过接口可以实现不相关类的相同行为,而不需要了解对象所对应的类。
 
  (2)通过接口可以指明多个类需要实现的方法。
 
  (3)通过接口可以了解对象的交互界面,而不需了解对象所对应的类。
 
 
  Clkrst给出了更详细的解释:
  类描述了一个实体,包括实体的状态,也包括实体可能发出的动作。
 
  接口定义了一个实体可能发出的动作。但是只是定义了这些动作的原型,没有实现,也没有任何状态信息。
 
  所以接口有点象一个规范、一个协议,是一个抽象的概念;而类则是实现了这个协议,满足了这个规范的具体实体,是一个具体的概念。
 
  从程序角度,简单理解,接口就是函数声明,类就是函数实现。需要注意的是同一个声明可能有很多种实现。
 
  所以就你的问题:
  1、接口中定义类方法的原型,但是不能说是空方法,因为空方法的意思是有实现体,只不过实现体是空操作。实际上接口没有定义任何实现体。具体的实现体都是在实现接口的类中,接口只是定义了这些方法的调用方式。
 
  你当然也可以不用接口,直接在类里面写方法,但是如果你的一组方法需要在很多类里实现,那么把它们抽象出来,做成一个接口规范,不是更好么?
 
  2、一个类描述了一个实体,这个实体可能是一个复杂的对象,它的动作很多,如果把这些动作分类,用接口a定义其中的某一组动作,接口b定义其中的另外一组动作,这样的结构,比较清楚。
 
  这种方式具备了多继承的优点,避免了多继承的缺陷。实际上在历史上,接口在很大程度上,是为了解决多继承带来的种种问题而设计出来的。
 
  3、包中那些已定义的接口,怎么知道那里面定义了什么方法。
 
  接口里定义了方法的输入输出,这些都是协议,具体的实现都在每个类中。对于很多只需要抽象接口的地方,不需要知道具体的类是什么,只要这个类实现了这个接口就可以了。*/










3.抽象类:abstract关键字
java中的特殊的类,这种类不能被实例化
抽象类也可以实现摸一个接口,我们可以直接在抽象类中直接实现接口,使得我们之后的抽象类的子类都不用去频繁的都去声明实现一个接口,但是我们可以声明要实现,抽象类中不一定要去实现接口的方法,我们交给子类去完成
因此在这里有一个编程的技巧就是,我们可以再抽象类中自己调用自己的方法,这是可以成功的,因为编辑器知道这些抽象的方法一定会被实现


总结:
接口可以实现的功能,抽象类都可以实现,而且抽象类还可以是实现其他的功能,但是并不能说抽象类比接口号,因为接口是允许多继承的,但是一个类只能继承一个类
1 0
原创粉丝点击