OOP其实也就是面向对象编程。
一:什么是对象:
我们最常见的理解方式无非是:对象(object)是任何看得见、摸得着、感觉得到,可以获得的东西,有自己的标识的任何东西。对象是某一类的事物的具体个例。比如这辆汽车、这个人、这间房子、这张桌子、这株植物、这张支票、这件雨衣,概括来说就是:万物皆对象。
在这里给大家摘录一些句子,希望看过的人能够花时间去思考一下:(有些还是不太懂啊啊。。。)
①“对象一般以域的形式包含数据,通常称作属性;以程序的形式包含代码,通常称作方法”。
②“对象在域中储存自身状态并通过方法暴露自身行为”。
③“每个对象就如一个小型电脑——它有状态,并且它提供操作,你可以调用执行”。
④“一个类包含了存放数值的数据域和操作数值的的方法”。
⑤“一个对象就是储存某些类型的值的内存空间”。
⑥“一个对象包含一些私有内存空间和一些操作”。
二:面向对象程序的设计方法:
(1)所有东西都是对象。可将对象想象成一种新型变量;它保存着数据,但可要求它对自身进行操作。理论上讲,可从要解决的问题身上提出所有概念性的组件,然后在程序中将其表达为一个对象。
(2)程序是一大堆对象的组合;通过消息传递,各对象知道自己该做些什么。为了向对象发出请求,需向那个对象“发送一条消息”。更具体地讲,可将消息想象为一个调用请求,它调用的是从属于目标对象的一个子例程或函数。
(3)每个对象都有自己的存储空间,可容纳其他对象。或者说,通过封装现有对象,可制作出新型对象。所以,尽管对象的概念非常简单,但在程序中却可达到任意高的复杂程度。
(4)每个对象都有一种类型。根据语法,每个对象都是某个“类”的一个“实例”。其中,“类”(Class)是“类型”(Type)的同义词。一个类最重要的特征就是“能将什么消息发给它?”。
(5)同一类所有对象都能接收相同的消息。这实际是别有含义的一种说法。由于类型为“圆”(Circle)的一个对象也属于类型为“形状”(Shape)的一个对象,所以一个圆完全能接收形状消息。这意味着可让程序代码统一指挥“形状”,令其自动控制所有符合“形状”描述的 对象,其中自然包括“圆”。这一特性称为对象的“可替换性”,是OOP
最重要的概念之一。
(6)一些语言设计者认为面向对象的程序设计本身并不足以方便解决所有形式的程序问题,提倡将不同的方法组合成“多形程序设计语言”。
三:对象的使用:
在这个例子中,类型/类的名称是 Light,可向 Light 对象发出的请求包括包括打开( on)、关闭( off)、变得更明亮( brighten )或者变得更暗淡( dim)。通过简单地声明一个名字( lt),我们为 Light 对象创建了一个“句柄”。然后用 new 关键字新建类型为 Light 的一个对象。再用等号将其赋给句柄。为了向对象发送一条消息,我们列出句柄名( lt),再用一个句点符号( .)把它同消息名称( on)连接起来。从中可以看出,使用一些预先定义好的类时,我们在程序里采用的代码是非常简单和直观的。
四:封装:
封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,以特定的访问权限来使用类的成员。隐藏之后,外部程序就不能接触和改变那些细节,所以不用担心自己的类会受到非法修改,可确保它们不会对其他程序造成影响。
封装的原则:
1. 将不需要对外提供的内容都隐藏起来;
2. 把属性都隐藏,提供公共方法对其访问。
1 package oop; 2 3 public class Student { 4 //属性私有化,避免属性被直接使用和修改 5 private String name; 6 private int age; 7 8 //对外提供公有的方法用来获取对象的属性值 9 public String getName() { 10 return name; 11 } 12 public void setName(String name) { 13 this.name = name; 14 } 15 //对外提供公有的方法用来获取对象的属性值 16 public int getAge() { 17 return age; 18 } 19 //对外提供公有的方法,可以对对象的属性进行控制,避免不合法的操作,可以对操作进行筛选 20 public void setAge(int age) { 21 if(age>120||age<=0){ 22 System.out.println("输入的年龄不合法!"); 23 }else{ 24 this.age = age; 25 } 26 } 27 28 static class test{ 29 public static void main(String[] args) { 30 Student s=new Student(); 31 s.setAge(130); 32 s.setAge(20); 33 System.out.println(s.getAge()); 34 } 35 } 36 }
五:继承:
我们费尽心思做出一种数据类型后,假如不得不又新建一种类型,令其实现大致相同的功能,那会是一件非常令人灰心的事情。但若能利用现成的数据类型,对其进行“克隆”,再根据情况进行添加和修改,情况就显得理想多了。“继承”正是针对这个目标而设计的。但继承并不完全等价于克隆。在继承过程中,若原始类(正式名称叫作基础类、超类或父类)发生了变化,修改过的“克隆”类(正式名称叫作继承类或者子类)也会反映出这种变化。在 Java 语言中,继承是通过 extends 关键字实现的。
1 package oop; 2 3 public class Father { 4 private String name; 5 6 public Father(String name) { 7 super(); 8 this.name = name; 9 } 10 11 public void getname(){ 12 System.out.println(name); 13 } 14 } 15 16 17 18 19 package oop; 20 21 public class Son extends Father{ 22 public Son(String name) { 23 super(name); 24 // TODO Auto-generated constructor stub 25 } 26 @Override 27 public void getname() { 28 // TODO Auto-generated method stub 29 super.getname(); 30 } 31 public static void main(String[] args) { 32 Son s=new Son("aa"); 33 s.getname(); 34 } 35 }
如果子类继承一个父类只是一个简单的继承,这意味着衍生类的对象不仅有相同的类型,也有同样的行为,这并不是我们想要的结果,一般我们,就像儿子继承父亲的财产,要进行有更进一步的发展一样。
第一种做法十分简单:为衍生类添加新函数(功能)。这些新函数并非基础类接口的一部分。进行这种处理时,一般都是意识到基础类不能满足我们的要求,所以需要添加更多的函数。这是一种最简单、最基本的继承用法,大多数时候都可完美地解决我们的问题(添加特定的方法,特殊的方法)。第二种做法是改变基础类一个现有函数的行为(重写父类的方法)。
第一种:添加方法
1 package oop; 2 3 public class Son extends Father{ 4 public Son(String name) { 5 super(name); 6 // TODO Auto-generated constructor stub 7 } 8 @Override 9 public void getname() { 10 // TODO Auto-generated method stub 11 super.getname(); 12 } 13 public void getouther(){ 14 System.out.println("hello"); 15 } 16 public static void main(String[] args) { 17 Son s=new Son("aa"); 18 s.getname(); 19 s.getouther(); 20 } 21 }
第二中:重写父类的方法:
1 package oop; 2 3 public class Son extends Father{ 4 public Son(String name) { 5 super(name); 6 // TODO Auto-generated constructor stub 7 } 8 @Override 9 public void getname() { 10 System.out.println("aaaaaaaaaaaaaaaaaaaaaa"); 11 } 12 }
JAVA中是单继承的,一个类只能继承一个父类。就像是一个孩子不管父亲是谁,只会有一个真正的父亲。
六:多态:
多态是同一个行为具有多个不同表现形式或形态的能力,多态就是同一个接口,使用不同的实例而执行不同操作,多态性是对象多种表现形式的体现。
多态的优点:
1. 消除类型之间的耦合关系
2. 可替换性
3. 可扩充性
4. 接口性
5. 灵活性
6. 简化性
多态存在的三个必要条件:
- 继承
- 重写
- 父类引用指向子类对象
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
例如:
1 package oop; 2 3 abstract class Animal { 4 abstract void eat(); 5 } 6 7 8 9 package oop; 10 11 public class Cat extends Animal{ 12 13 @Override 14 void eat() { 15 // TODO Auto-generated method stub 16 System.out.println("吃鱼"); 17 } 18 public void work(){ 19 System.out.println("抓老鼠"); 20 } 21 } 22 23 24 25 26 package oop; 27 28 public class Dog extends Animal{ 29 30 @Override 31 void eat() { 32 // TODO Auto-generated method stub 33 System.out.println("吃烤翅"); 34 } 35 public void work(){ 36 System.out.println("看家"); 37 } 38 } 39 40 41 42 43 44 package oop; 45 46 public class Test { 47 48 public static void main(String[] args) { 49 // TODO Auto-generated method stub 50 duotai(new Cat()); 51 duotai(new Dog()); 52 } 53 public static void duotai(Animal a){ 54 if(a instanceof Cat){ 55 Cat cat=(Cat) a; 56 cat.eat(); 57 cat.work(); 58 }else{ 59 Dog dog=(Dog) a; 60 dog.eat(); 61 dog.work(); 62 } 63 } 64 }
七:抽象类:
设计程序时,我们经常都希望基础类只为自己的衍生类提供一个接口。也就是说,我们不想其他任何人实际创建基础类的一个对象,只对上溯造型成它,以便使用它们的接口。为达到这个目的,需要把那个类变成“抽象”的—— 使用 abstract 关键字。若有人试图创建抽象类的一个对象,编译器就会阻止他们。这种工具可有效强制实行一种特殊的设计。
亦可用 abstract 关键字描述一个尚未实现的方法—— 作为一个“根”使用,指出:“这是适用于从这个类继承的所有类型的一个接口函数,但目前尚没有对它进行任何形式的实现。”抽象方法也许只能在一个抽象类里创建。继承了一个类后,那个方法就必须实现,否则继承的类也会变成“抽象”类。通过创建一个抽象方法,我们可以将一个方法置入接口中,不必再为那个方法提供可能毫无意义的主体代码。
interface(接口)关键字将抽象类的概念更延伸了一步,它完全禁止了所有的函数定义。“接口”是一种相当有效和常用的工具。另外如果自己愿意,亦可将多个接口都合并到一起(不能从多个普通 class 或abstract class 中继承)。比如上面的示例代码就将父类以及父类的方法进行了抽象,因为父类并不需要做任何实际的事情。
一