[Java]开发安卓,你得掌握的Java知识6——封装、继承、多

2019-08-10  本文已影响0人  入梦瞌睡

目录

1.本文主要内容简介

2.基础知识讲解

3.知识实际运用

4.总结

0.前言

1.本文主要内容简介

2.基础知识讲解

2.1什么是代码块

  • 从观角度来说,
    代码块就是在类中,用{ }括起来的部分

  • 从程序运行的角度来讲
    代码块就像静态属性、方法一样,会早于对象被创建

  • 一个程序可以有多个代码块,执行顺序是从上倒下
    但是注意:
    尽可能不要写多个代码块(因为没有意义,可以写在一起)

class Person{
    int age;
    {
        age = 20;
        System.out.println("代码块 age="+age);
    }
    {
        age=30
        System.out.println("代码块 age="+age);
    }

}
  • 用“static”修饰的代码块是静态代码块
    静态代码块就和静态方法一样,会在对象创建前就被创建,因此
    静态代码块只能调用静态属性、方法
    static{
       //静态代码块
    }

2.2什么是内部类

  • 按字面意思理解即可,内部类就是写在其他类内部的类

  • 内部类出现的原因主要是因为某些类需要依附着别的类

  • 定义内部类的好处在于:
    (1)内部类实际上是一种很好的封装
    (2)内部类拥有外围类的所有元素的访问权限
    (3)内部类在外围类被某个子类继承时,内部类会跟着继承

内部类的一些细节:

  • 如果有内部类,一般会在外围类的属性中,
    声明一个内部类变量(不赋值)
  • 一般为了封装性好,我们不会让外部去调用我们的内部类,
    一般不能让Test.InnerTest.方法名()出现
    (当然真这样写程序不会报错,但是封装性会变差)

  • 为了避免上面的这种情况,我们会在外围类的某个方法中,将已经声明过的内部类的变量用new进行赋值,然后根据内部类的构造方法等函数使用内部类

  • 为了封装性,最关键就是让外部不知不觉地调用内部类,而不是显式调用

public class Test{
   int count;
   InnerTest inner;
   class InnerTest{
       //这是一个内部类
       public InnerTest(){
            //这是内部类的构造方法
            count = 2;
            show();
       }
   }
   
   public void test(){
       //这个函数是给外部调用的
       inner = new InnerTest();
   }
   public void show(){
        System.out.println("内部类构造函数被执行了");
   }
}

public static void main(String[] args){
      Test temp = new Test();
      temp.test();
}
上面这段代码看似有点复杂,我们慢慢理一下

2.4什么是继承

  • 某个准备编写的类A中的内容,和已存在的类B中很相似,或者A中的内容是B的一个延伸拓展,那么我们不会傻乎乎地再从头写一遍A
    而是让A去继承B

  • class A extends B , 表示类A是继承类B的

  • 当A继承了B后,A就可以使用B的属性、方法(即使A中没有声明)

  • Java中只能单继承,不能多继承,最多只能间接多继承
    即(A继承B,B继承C,相当于A继承C,变相多继承)

  • 所有的类都是直接或者间接继承与Object类

class Person{
    protected String name;
    protected int age;

    public Person() {

    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void walk(){
        System.out.println("走");
    }
}


class Student extends Person{
    public String school;
    public int id;

    public Student(String name, int age, int id, String school) {
        super(name,age);
        this.id = id;
        this.school = school;
        this.age = age;
        this.name = name;
    }

    @Override
    public void walk() {
        System.out.print("学生优雅地");
        super.walk();
    }
}
上面代码的注意点:
  • 父类为Person类,子类为Student类

  • 父类想要保证属性的私有性,又要保证能够被继承,会让属性被protected修饰

  • public与protected修饰的属性是可以被继承的,但是private不行

  • 如果父类中,已经写了一个有参的构造函数,那么子类再写有参的构造函数且要用到父类属性的时候,需要写一个super(参数...)
    来说明哪些属性来自于父类

2.5什么是重写

  • 重写就是子类将父类的方法拿到自己这里进行修改

  • 重写的方法一般会在上面加上 @Override,来表示这是重写的方法

  • 重写与重载是两码事
    重写是针对继承来说的,是子类修改父类的方法
    重载是针对一个类来说的,是类中会有多个同名的方法,但是这些方法的参数种类、数量,以及方法返回值都不尽相同

@Override
    public void walk() {
        System.out.print("学生优雅地");
        super.walk();
    }

上面的代码就是重写,其中super表示父类super.walk()就表示
这次重写除了自己新增那部分,还要用到父类的方法

2.6什么是多态

  • 多态简单来说有两种体现:
    (1)同一个方法(在不同类中)有多种不同的实现(与重载不一样)
    (2)如果有继承关系(必须的前提,直接继承、间接继承都行)
    子类的对象可以使用父类变量接收(叫做“类型的向上转换”)

  • 多态关注的是同一个方法在不同类中的实现,
    重载是同一个方法名但是参数、返回值不同

class A{
}
class B extends A{
}
A test = new B();
Object test2 = new B();
List<Integer> list = new ArrayList<>();

这些都是多态的体现,当然更实际一些的应用在于:

class Person{}
class Student extends Person{}
class Teacher extends Person{}
Student s1 = new Student();
Teacher t1 = new Teacher();
ArrayList<Person> list = new ArrayList<>();
list.add(s1);
list.add(t1);

3.实际应用

  • 定义一个Person类:有name age两个属性
    提供有参数的构造方法
    walk方法
    eat方法

  • 公务员:salary(工资) , show()
    公司职员:salary ,会什么技术tec(字符串),show()

  • 创建多个职员和公务员 放到一个数组里面
    将数组里面所有人的信息输出(把所有方法都显示出来)

要完成这个小程序,要一步步考虑:
(1)需要将多个人放到数组里
(2)放到数组里的要分为两种类型,公务员类和公司职员类
(3)这两个类都继承与Person类,还有自己的属性salary等
(4)Person类中有两个属性name age
     以及两个方法walk(),eat()
(5)两个继承类均有自己的show()方法来展示信息

  • 我们首先要定义一个Person类,并构造一个有参的构造方法。
    这个父类基本不需要怎么处理,照着要求做即可
public class Person {
    public String name;
    public int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void walk(){
        System.out.println("人会走路");
    }
    public void eat(){
        System.out.println("人会吃");
    }
}
  • 然后,我们需要按要求写两个继承类
    Clerk(银行职员)和CivilServant(公务员)
    没什么难度,因为子类没有什么额外的方法
public class Clerk extends Person {
    public int salary;
    private String tec;

    public Clerk(String name, int age, int salary) {
        super(name,age);
        this.salary = salary;
    }
    @Override
    public void walk() {
        System.out.print(" 快跑 ");
    }

    @Override
    public void eat() {
        System.out.print(" 吃得快 ");
    }

}

public class CivilServant extends Person {
    public int salary;//薪水

    public CivilServant(String name, int age, int salary) {
        super(name,age);
        this.salary = salary;
    }

    @Override
    public void walk() {
        System.out.print(" 大步走 ");
    }

    @Override
    public void eat() {
        System.out.print(" 大方吃 ");
    }

}
  • 接下来问题在于如何把人放入数组中
    为了方便,我们定义几个静态数组来存放默认的人以及他们的信息,这些静态数组方法Constant类中
public class Constant {
    public static String[] PERSONS = {"小王","小红","小黑","小蓝"};
    public static int[] PERSONSAGES = {20,19,25,16};
    public static String[] OCCUPATIONS= {"CivilServant","Clerk","CivilServant","Clerk"};
    public static int CIVILSERVANTSALARY = 10000;
    public static int CLERKSALARY = 5000;
    public static String[] TEC= {"Android开发","iOS开发"};
}
  • 有了这些信息之后,我们就需要将这些信息放入ArrayList中,由于CivilServant与Clerk虽然是不同的类,但是都继承于Person类
    因此ArrayList的泛型就可以写<Person>

  • 为了封装性好一些,我们可以专门定义一个PersonManager,来处理人的信息(比如把信息打包放入数组中)

public class PersonManager {
    public List<Person> personList = new ArrayList<>();
    
}
  • 我们在PersonManager里面写一个方法来把静态数组中的信息放入personlist中
public void InfoInput(){
        //用来将Constant类中的内容放入数组中
        for (int i = 0; i < Constant.PERSONS.length; i++) {
            if (Constant.OCCUPATIONS[i] == "CivilServant") {
                this.personList.add(new CivilServant(Constant.PERSONS[i],Constant.PERSONSAGES[i],Constant.CIVILSERVANTSALARY));
            }else{
                //否则就是Clerk
                this.personList.add(new Clerk(Constant.PERSONS[i],Constant.PERSONSAGES[i],Constant.CLERKSALARY));
            }

        }
    }
  • 最后我们写一个方法来输出,其中要注意的是,
    父类是无法使用子类的方法的,要使用子类的方法,
    就必须把父类强制转换为子类

    如下面代码中的 Clerk c = (Clerk)p;,然后通过c调用show()方法
 public void showWorkerInfo(){
        //将所有人的所有信息都显示出来
        for(Person p : personList){
            if(p instanceof CivilServant){
                CivilServant c = (CivilServant)p;
                c.show();
            }else{
                //是银行职员
                Clerk c = (Clerk)p;
                c.show();
            }
        }
    }

别忘记还要再两个继承类中添加show()方法:

public void show() {
        System.out.print("name:" + this.name + " age:" + this.age + " salary:" + this.salary + " 公务员会");
        this.walk();
        this.eat();
        System.out.println();
    }
public void show() {
        System.out.print("name:" + this.name + " age:" + this.age + " salary:" + this.salary + " 银行职员会");
        this.walk();
        this.eat();
        System.out.println();
    }

通过以上的封装后,主函数就可以写的比较清晰简洁了

public static void main(String[] args) {
        //创建一个PersonManager对象
        PersonManager personManager = new PersonManager();
        
        //把所有人放入数组中
        personManager.InfoInput();

        //把输出所有人
        personManager.showWorkerInfo();

    }

输出结果为:

name:小王 age:20 salary:10000 公务员会 大步走 大方吃
name:小红 age:19 salary:5000 银行职员会 快跑 吃得快
name:小黑 age:25 salary:10000 公务员会 大步走 大方吃
name:小蓝 age:16 salary:5000 银行职员会 快跑 吃得快

ps:代码只是用来做个例子,输出结果没有任何其他意思

4.总结

(1)今天主要讲解了与类的继承有关的知识,继承、多态、封装也算是面向对象的灵魂,需要多多注意
(2)继承、多态等新知识,实际上理论都不难,但是如果想要灵活运用,还是需要多多练习
(3)可以发现,Java的代码编写一直都离不开“封装”的思想,因此,日后的学习中,锻炼这一思想,应该要当做一个重点看待。

上一篇下一篇

猜你喜欢

热点阅读