面向对象
面向过程 & 面向对象
面向过程思想
- 步骤清晰简单,第一步做什么,第二步做什么
- 面向过程适合处理一些较为简单的问题
面向对象思想
- 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
总结:对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观 操作,还是需要面向过程的思路去处理。
什么是面向对象
面向对象编程(Object-Oriented Programming)简称OOP
面向对象编程的本质就是:以类的方式组织代码,以对象的方式封装数据
面向对象的三大特性:封装,继承,多态。
抽象:从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征的过程,在Java中抽象就是将事物抽象成类,类中的属性和方法都是这个事物的一些基本的特征。
从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
从代码运行角度考虑是先有类后有对象。类是对象的模板。
创建和初始化对象
- 使用new 关键字创建对象
- 使用new关键字创建的时候,除了分配内存空间之外,还会给创建 好的对象进行默认初始化以及对类中构造方法的调用
方法的调用
静态方法和非静态方法
静态方法就是使用static修饰的方法,非静态方法就是没有用static修饰的方法。
静态方法是和类一起加载的,而非静态方法需要类实例化之后才被加载
非静态的方法需要实例化一个对象才能调用,而静态的方法可以直接使用类名.方法名来调用
public class Student {//学生类
//静态方法Student student= new Student();//实例化了一个对象
// student.say();//非静态方法的调用
public static void study(){
System.out.println("学生学习了");
}
//非静态方法Student.study();//静态方法的调用,可以直接类名.方法名
public void say(){
System.out.println("学生说话了");
}
}
形参和实参
//实际参数和形式参数的类型要对应
Dome01.add(1,2);
}
public static int add(int a,int b){//方法名后面的括号里面的是形式参数
return a+b;
}
值传递和引用传递
public class Dome02 {
public static void main(String[] args) {
//值传递
int a=1;
System.out.println(a);//1
Dome02.change(a);
System.out.println(a);//1
}
//返回值为空的静态方法
public static void change(int a){
a=10;
}
}
public class Dome03 {//引用传递,对象,本质上还是值传递
public static void main(String[] args) {
Person person=new Person();
System.out.println(person.name);//null
Dome03.change(person);
System.out.println(person.name);//wang
}
public static void change(Person person){
//person是一个对象,指向的--->Person person=new Person();这是一个具体的人可以改变属性
person.name="wang";
}
}
//定义了一个person类,其中有一个属性
class Person{
String name;//没有赋值,默认为null
}
this关键字
- 在类的方法定义中使用的this关键字代表使用该方法的对象的引用
- 当必须指出当前使用方法的对象是谁时可以使用this
- this可以看作一个变量,它的值是当前对象的引用
public class Dome05 {
int i=0;//类中的属性,也就是成员变量
public static void main(String[] args) {
Dome05 dome05=new Dome05();
dome05.test(5);//5
int a=dome05.i;//调用这个类的属性
System.out.println(a);//5
}
public void test(int i){
this.i=i;//将这个方法中的实参的值赋给了这个成员变量
System.out.println(i);
}
}
构造方法
类中的构造器也称为构造方法,是在进行创建对象的时候必须调用的。并且构造器有以下两个特点
-
- 必须和类名相同
- 必须没有返回类型,也不能写void
public class Pet {
String name;
int age;
public Pet(){
//这是一个无参构造
}
public Pet(String name,int age){//这是一个有参的构造方法
this.age=age;
this.name=name;
}
}
public static void main(String[] args) {
//实例化一个对象的时候就是调用了一个无参的构造方法
Pet pet=new Pet();
//下面这个调用的是一个有参的构造方法
Pet pet1=new Pet("wangcai",2);
}
}
使用new关键字本质上还是调用了无参的构造方法初始对象的值。
当一个类中没有定义构造方法时,默认的会执行一个无参的构造方法,但如果定义了一个有参的构造的时候,就要写出那个无参的构造,否则就不能使用那个无参的构造方法。
封装
封装就是将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来对隐藏的信息进行操作和访问。
总结来说就是:属性私有,get/set方法
封装的实现步骤
- 修改属性的可见性设为(private)
- 创建getter/setter方法(用于属性的读写)(通过这两种方法对数据进行获取和设定,对象通过调用这两种发方法实现对数据的读写)
- 在getter/setter方法中加入属性控制语句(对属性值的合法性进行判断)
public class Pr {//该类封装了三个属性
private int age;//私有的属性,只有本类能使用,不能在外面进行赋值和更改,但可以通过其提供的方法进行设置
private String name;
private char sex;
public int getAge() {
return age;
}
public void setAge(int age) {
if(0>age || age<120){//设置年龄的取值范围
this.age = age;
}else{
this.age=3;
}
}
public String getName() {
return name;
}
public void setName(String name)
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
继承
- 继承的本质是对某一批类的抽象,从而实现对现实世界的更好建模。
- extends的意思是“扩展”,子类是父类的扩展。
- Java类中只有单继承,没有多继承。
- 继承是类和类之间的一种关系,除此之外,类和类之间的关系还有依赖,组合,聚合等。
- 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
/*KiKi理解了继承可以让代码重用,
他现在定义一个基类shape,私有数据为坐标点x,y,
由它派生Rectangle类和Circle类,它们都有成员函数GetArea()求面积。
派生类Rectangle类有数据:矩形的长和宽;派生类Circle类有数据:圆的半径。
Rectangle类又派生正方形Square类,定义各类并测试。
输入三组数据,分别是矩形的长和宽、圆的半径、正方形的边长,输出三组数据
,分别是矩形、圆、正方形的面积。圆周率按3.14计算。
* */
public class shape {
private int x;
private int y;
}
==============================================================================
package com.oop;
public class Rectangle extends shape {
double a;//矩形的长
double b;//矩形的宽
public double getArea(double a,double b){//计算面积的方法
return a*b;
}
}
===============================================================================
package com.oop;
public class Circle extends shape{
int r;//园的半径
public double getArea(double r){//返回圆的面积
return (3.14*r*r);
}
}
=================================================================================
package com.oop;
public class Square extends Rectangle {
public double getArea(double s) {
return s*s;
}
}
=================================================================================
package com.oop;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("请输入你要数据:");
if(scanner.hasNextDouble()){
double a=scanner.nextDouble();
double b=scanner.nextDouble();
double r = scanner.nextDouble();
double s= scanner.nextDouble();
Rectangle rectangle=new Rectangle();
double area=rectangle.getArea(a,b);
System.out.println("长方形的面积为"+area);
Circle circle=new Circle();
System.out.println("圆的面积"+circle.getArea(r));
Square square=new Square();
System.out.println("正方形的面积"+square.getArea(s));
}
scanner.close();
}
}
多态
多态是方法的多态,属性没有多态性
- 什么是多态呢?
- 即同一个方法可以根据发送对象的不同而采用多种不同的行为方式。
- 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关系的类)。
多态存在的条件
- 有继承关系
- 子类重写父类的方法
- 父类引用指向子类对象
方法的重写
方法的重写需要有继承关系,子类重写父类的方法
重写的规则
- 方法名必须相同
- 参数列表必须相同
- 修饰符范围可以扩大但不能缩小:public>protected>Default>private
- 抛出的异常范围可以被缩小,但不能扩大
方法重写和重载的区别
重写:子类的方法必须和定义类一致,只是方法体不同
重载:方法的方法名一致,参数列表中的参数和不同,参数的个数可以不同,参数的排列顺序可以不同
public class Person_01 {
/**
* 2.定义一个人的类(属性有名字,年龄。写一个能输出各个属性值
* 的方法showInfo(),定义一个学生类(属性有性别),学生继承人类
* 要求:
* (1)父类的属性赋值用构造方法来实现(分别用有参数构
* 造方法和无参数构造方法实现)
* (2)子类的属性也用构造方法来赋值。
* (3)在子类中重写父类的
* showInfo()方法
* (4)声明学生类的对象,调用学生的显示信息的方法。
* */
String name;
int age;
public void Person_01(){
}
public void Person_01(String name,int age){
this.name=name;
this.age=age;
}
public void showInfo(){
System.out.println("名字"+name+"年龄"+age);
}
}
public class Student_01 extends Person_01{
char sex;
String name;
int age;
public Student_01(char sex, String name, int age) {
this.sex = sex;
this.name = name;
this.age = age;
}
@Override
public void showInfo() {
System.out.println("输出学生的名字和年龄和性别"+sex+name+age);
}
}
public class Dome {
public static void main(String[] args) {
Student_01 student01=new Student_01('男',"wang",14);
student01.showInfo();
}
}