面向对象编程:封装,继承,多态

封装

封装概述

封装(Encapsulation)是面向对象方法的重要原则,就是把对象的属性和操作(或服务)结合为一个独立的整体,并尽可能隐藏对象的内部实现细节。

类是Java中最小的一个单位,它体现了一种封装的思想,封装了成员变量(属性)和成员方法(功能)
如何定义一个类

class 类名{
成员变量
成员方法(){
}
}

如何使用类
类是一个很抽象的概念,无法直接使用,若想使用该类,需要先对其进行实例化,即创建该类的对象,对象时该类的具体表现
** 如何创建对象**
使用 new关键字就可以创建该类对象
格式

类名 对象名 = new 类名();

比如说现在有一个student

Student   s=new Student()

方法

Java方法是语句的集合,它们在一起执行一个功能
方法的定义

修饰符 返回值类型 方法名(参数类型 参数名){
    ...
    方法体
    ...
    return 返回值;
}
  • 修饰符:是可选的,它定义了方法的访问类型。
  • 返回返回类型:void是指没有没有特定的返回值,但如果改为其他的例如int ,double那么就一定要有一个返回值了
  • 方法名:是该方法的名字,由大家自己定义
  • 参数类型:声明了参数的数据类型,例如第一个例子中的int表示参数是int类型
  • 参数名:参数的名字,例如第一个代码例子中的a和b就是参数的名字
  • 方法体:该方法具体想实现的功能
  • return:结束方法,并返回指定的类型
  • 返回值:方法的结果,由return带回
    ** 方法的调用**
    Java 支持两种调用方法的方式,根据方法是否返回值来选择。当程序调用一个方法时,程序的控制权交给了被调用的方法。当被调用方法的返回语句执行或者到达方法体闭括号时候交还控制权给程序。
    1.当方法返回一个值的时候,方法调用通常被当做一个值
    2.如果方法返回值是void,方法调用一定是一条语句。
    例:
class demo1{
    public static void main(String[] args) {
        test1();
        System.out.println(test2());
    }
    public static void test1() {
        System.out.println("你好世界");
    }
    public static int test2(){
        return 2;
    }
}

通过值传递参数
在定义方法时,如果定义了形式参数,那么在调用时就要提供参数,要按照参数列表所给定的顺序传入

 public static void test(int a,String b){
        System.out.println(b+"-----------"+a);
    }

此方法在调用时就需要传入两个参数,第一个是int类型的,第二个是String类型的

test2(5,"name");

** 方法重载**
方法重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数,方法重载与返回值类型,返回值,参数名都没有关系。
构造方法
语法
方法名和类名相同,没有返回值类型,连void都没有。根据方法有无参数,我们将其分为有参构造方法和无参构造方法,在我们定义的类中都会有一个默认的无参构造
举例

public Student(){
	System.out.println("这是一个无参构造");
}
public Student(){
	System.out.println("这是一个有参构造");
	this.name=name;
}

注意:在一个类中,如果写了一个有参构造,那么就不会有默认的无参构造方法了,如果要用到无参构造方法需要自己写一个。
作用
用来完成对类的初始化

代码块

** 概述**
在Java中,使用{}括起来的代码被称为代码块。
局部代码块
在方法中出现;限定变量生命周期,及早释放,提高内存利用率
举例

public class demo {
    public static void main(String[] args) {
        { 
            int x = 3;
            System.out.println("普通代码块内的变量x=" + x);
        }
        int x = 1;
        System.out.println("主方法内的变量x=" + x);
        
    }
} 

构造代码块
在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行
举例

class test{
    public test(){
        System.out.println("这是一个无参构造方法");
    }
    public test(int a){
        System.out.println("这是一个有参构造方法,参数是a,a="+a);
    }
}
public class demo {
    public static void main(String[] args) {
        new test();
        new test(5);
    }
}

静态代码块
在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且只执行一次。
举例

class test{
    public test(){
        System.out.println("这是一个无参构造方法");
    }
    public test(int a){
        System.out.println("这是一个有参构造方法,参数是a,a="+a);
    }
    static {
        System.out.println("test的静态代码块");
    }
}
public class demo {
    public static void main(String[] args) {
        new test();
        new test(5);
    }
}

封装的好处

1.对象的数据封装特性彻底消除了传统结构方法中数据与操作分离所带来的种种问题,提高了程序的可复用性和可维护性,降低了程序员保持数据与操作内容的负担。
2.对象的数据封装特性还可以把对象的私有数据和公共数据分离开,保护了私有数据,减少了可能的模块间干扰,达到降低程序复杂性、提高可控性的目的

继承

继承概述

继承是面向对象最显著的一个特性,Java继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。关键字:extent
** 继承的格式**

class 子类名 extent  父类名{
}

** 继承的注意事项**
1.父类私有成员无法被继承(private修饰的)
2.构造方法不参与继承
3.Java中不支持多继承,但支持多层继承
4.不要为了一小部分功能使用继承,这会增加代码的耦合性
这与代码开发规则:高内聚,低耦合 相悖

关键字this与super

this 代表本类的一个引用,可以理解为本类的一个对象,谁调用就代表谁
super 是父类空间的标识,可以理解为父类的一个对象
this的用法
1.普通的直接引用
这种就不用讲了,this相当于是指向当前对象本身
2.形参与成员名字重名,用this来区分:

class Person {
    private int age = 10;
    public Person(){
    System.out.println("初始化年龄:"+age);
}
    public int GetAge(int age){
        this.age = age;
        return this.age;
    }
}
 
public class test1 {
    public static void main(String[] args) {
        Person Harry = new Person();
        System.out.println("Harry's age is: "+Harry.GetAge(12));
    }
}       

输出为

初始化年龄:10
Harry's age is:12

3.引用构造函数
放在下面和super一起看
super用法
1.值接引用
指向当前对象的父类,super.XXX表示父类的成员
2.子类中的变量和方法与父类中的重名
例如:

 class people {
    String name;
    public void demo(){
        name="小刚";
    }
}
class student extends people{
    String name="小明";
    public void demo() {
        super.demo();//调用父类方法
        System.out.println(name);
        System.out.println(super.name);
    }

    public static void main(String[] args) {
        student st= new student();
        st.demo();
    }
}

运行结果

小明
小刚

3.引用构造函数
super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。
this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。

class Person { 
    public static void prt(String s) { 
       System.out.println(s); 
    } 
   
    Person() { 
       prt("父类·无参数构造方法: "+"A Person."); 
    }//构造方法(1) 
    
    Person(String name) { 
       prt("父类·含一个参数的构造方法: "+"A person's name is " + name); 
    }//构造方法(2) 
} 
    
public class Chinese extends Person { 
    Chinese() { 
       super(); // 调用父类构造方法(1) 
       prt("子类·调用父类”无参数构造方法“: "+"A chinese coder."); 
    } 
    
    Chinese(String name) { 
       super(name);// 调用父类具有相同形参的构造方法(2) 
       prt("子类·调用父类”含一个参数的构造方法“: "+"his name is " + name); 
    } 
    
    Chinese(String name, int age) { 
       this(name);// 调用具有相同形参的构造方法(3) 
       prt("子类:调用子类具有相同形参的构造方法:his age is " + age); 
    } 
    
    public static void main(String[] args) { 
       Chinese cn = new Chinese(); 
       cn = new Chinese("codersai"); 
       cn = new Chinese("codersai", 18); 
    } 
}

继承的中构造方法
继承中构造函数的关系
子类中所有的构造方法默认都会访问父类中空参数的构造方法。这是因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化,每一个构造方法的第一条语句默认都是:super(),这一点在上面的super和this的用法中也有提到
** 继承中构造方法的注意事项**
如果父类没有无参构造方法,子类初始化怎么办?
1. 在父类中添加一个无参的构造方法
2.子类通过super去显示调用父类其他的带参的构造方法
3.子类通过this去调用本类的其他构造方法,本类其他构造也必须首先访问了父类构造
注意事项
super(…)或者this(….)必须出现在第一条语句上,这在上面的super和this的用法中也有提到
** 方法重写**
当父类和子类的方法申明(方法名,返回值类型,参数列表)一样时,子类的方法就会覆盖掉父类的方法,这样的现象称之为方法重写。当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。这样,即沿袭了父类的功能,又定义了子类特有的内容。
举例

class animal{
    int age;
    public void eat(){
        System.out.println("吃东西");        
    }
}
class cat extends animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
class dog extends animal{
    public void eat() {
        System.out.println("狗吃肉");
    }
}

方法重写的注意事项
1.父类中私有方法不能被重写,因为父类私有方法子类根本就无法继承
2.:子类重写父类方法时,访问权限不能更低最好就一致
(四个权限修饰符 public> (空缺的,什么都不写) >protect>private )
3.静态方法不参与重写

final关键字

** final用法**
由于继承中有一个方法重写的现象,而有时候我们不想让子类去重写父类的方法.这对这种情况java就给我们提供了一个关键字: final
final可以修饰类,成员方法,变量

final class demo {
    final  int a=100;//变量变为常量
    public final void show(){
    } //该该方法无法被重写
}//该类无法被继承

** final修饰特点**
修饰类: 被修饰类不能被继承
修饰方法: 被修饰的方法不能被重写
修饰变量: 被修饰的变量不能被重新赋值,因为这个量其实是一个常量
修饰引用类型:其地址无法被修改

继承的优点与弊端

优点
1.提高了代码的复用性
2.提高了代码的维护性
3.让类与类之间产生了关系,是多态的前提
弊端
增加了代码的耦合性,这违背可开发的原则:高内聚,低耦合

多态

多态概述

在面向对象语言中,接口的多种不同的实现方式即为多态,简单的说,就是允许将子类类型的指针赋值给父类类型的指针。

Cat c=new Cat();
Animal a=new Cat();

多态存在的必要条件

1.继承
2.方法重写
3.父类引用指向子类

多态中成员访问特点

1.成员变量:编译看左边,运行看左边
2.构造方法:创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化。
3.成员方法:编译看左边,运行看右边。
4.静态方法:编译看左边,运行看左边。
(静态和类相关,算不上重写,所以,访问还是左边的)

class Super {
	int index = 5;
	public void printVal() {
		System.out.println("Super");
	}
}
class Sub extends Super {
	int index = 2;
	public void printVal(){
		System.out.println("Sub");
	}
}
class Demo {
	public static void main(String[] args) {
		Super sup = new Sub();
		System.out.print(sup.index + ",");//成员变量:编译看左边,运行看左边
		sup.printVal();//成员方法:编译看左边,运行看右边
	}
}

多态的优点以及弊端

优点
1.提高了代码的维护性(继承保证)
2.提高了代码的扩展性(由多态保证)
弊端
不能使用子类特有的功能

向下转型

把父类的引用强制转换为子类的引用。用来解决多态的弊端
举例

public class MyTest{
    public static void main(String[] args) {
        Fu fu = new Zi();
        System.out.println(fu.num);
        fu.show();
        Zi zi= (Zi) fu;//向下转型
        System.out.println(zi.num);
        zi.mehtod();
    }

}

class Fu{
    int num=100;
    public void show(){
        System.out.println("fu  show");
    }
}
class Zi extends Fu{
    int num=10;

    @Override
    public void show() {
        System.out.println("zi show");
    }
    public void mehtod(){
        System.out.println("子类特有的方法");
    }
}

猜你喜欢

转载自blog.csdn.net/rtx_2080/article/details/85080534