美文网首页
面向对象

面向对象

作者: hey_leex | 来源:发表于2018-01-05 17:03 被阅读0次

    面向对象

    封装

    1. 是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
    2. 提高了代码的复用性,安全性

    通过对象去给成员变量赋值,可以赋值一些非法的数据。

    public class Student(){
        public int age;
    }
    //main
    Student s = new Student();
    s.age = -1;                 //这是不合理的
    

    所以我们将属性封装起来,并让外界通过我指定的通道访问和修改我的属性
    用private修饰属性

    private关键字:

    • 是一个权限修饰符。

    • 可以修饰成员(成员变量和成员方法)

    • 被private修饰的成员只在本类中才能访问

        public class Student(){
            private int age;
      
            public int getAge(){
                return this.age;
            }
            public void setAge(int age){
                if(age>0&&age<120){
                    this.age = age;
                }else{
                    system.out.println("输入错误");
                }
            }
        }
        //main
        Student s = new Student();
        s.age = -1;                 //输入错误
      

    继承

    概述

    1. 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
    2. 通过extends关键字可以实现类与类的继承
      class 子类名 extends 父类名 {}
    3. 单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。
    4. 有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员。

    好处

    1. 提高了代码的复用性

      • 多个类相同的成员可以放到同一个类中
    2. 提高了代码的维护性

      • 如果功能的代码需要修改,修改一处即可
    3. 让类与类之间产生了关系,是多态的前提
      其实这也是继承的一个弊端:类的耦合性很强

       开发的原则:低耦合,高内聚。
           耦合:类与类的关系
           内聚:就是自己完成某件事情的能力
      

    java继承的注意

    1. java只支持单继承,不支持多继承。
      一个类只能有一个父类,不可以有多个父类。

       class Son extends Futher{} //ok
       class Son extends Futher,Mother{}//error
      
    2. Java支持多层继承(继承体系)

       class GrandFuther{}
       class Futher extends GrandFuther{}
       class Son extends Futher{}
      
    3. 子类只能继承父类所有非私有的成员(成员方法和成员变量)

    4. 子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。

    5. 不要为了部分功能而去继承

           class A {
               public void method1(){}
               public void method2(){}
           }
           
           class B {
               public void method2(){}
               public void method3(){}
           }
           
           //我们发现B类中出现了和A类一样的method2()方法,所以,我们就用继承来体现
           class B extends A {
               public void method3(){}
           }
           这样其实不好,因为这样你不但有了method2(),还多了method1()。
           有可能method1()不是你想要的。
           
       什么时候考虑使用继承呢?
       继承其实体现的是一种关系:"is a"。
           Person
               Student
               Teacher
       Student是Person的一种
      
    6. 直接调用属性名时,同名属性的查找顺序(就近原则)

      子类方法局部->子类成员->父类成员->找不到报错(单层继承情况下)

      同: 属性 -> this.属性 -> super.属性

    this&super

    不能在static中使用,static属于类的

    1. 调用成员变量

      • this.成员变量 调用本类的成员变量
      • super.成员变量 调用父类的成员变量
    2. 调用构造方法

      • this(...) 调用本类的构造方法
      • super(...) 调用父类的构造方法
    3. 调用成员方法

      • this.成员方法 调用本类的成员方法
      • super.成员方法 调用父类的成员方法

    构造函数的关系

    子类不继承父类的构造函数,可以用super调用

    子类中所有的构造方法再不写super的情况下默认都会访问父类中空参数的构造方法

    因为子类会继承父类中的数据,可能还会使用父类的数据。

    所以,子类初始化之前,一定要先完成父类数据的初始化。

    注意:子类每一个构造方法的第一条语句默认都是:super(),即使删除也有;

    当子类没有构造函数的时候,系统默认提供一个无参构造方法

    public class Fu {       //父类,提供了有参构造,所有系统不会提供一个无参构造,即没有无参构造
        private String str = "name";
        private int i = 1;
    
        public Fu(String str, int i) {
            this.str = str;
            this.i = i;
        }
    }
    //--------------------
    public class Zi extends Fu{//子类没有提供构造函数,系统自动提供一个无参构造,但是无参构造第一句默认super(),父类没有,报错
                            //error:Implicit super constructor Fu() is undefined. Must explicitly invoke another constructor
                            //隐式的父类构造函数fu()是未定义的。必须显式调用另一个构造函数 
    }
    //--------------------
    public class Zi extends Fu{//子类也无法提供无参构造
        public Zi() {
                            //error:Implicit super constructor Fu() is undefined. Must explicitly invoke another constructor
                            //隐式的父类构造函数fu()是未定义的。必须显式调用另一个构造函数 
        }
    }
    
    • 子类通过super去显示调用父类其他的带参的构造方法
    • 子类通过this去调用本类的其他构造方法
    • 本类其他构造也必须首先访问了父类构造

    一定要注意:

    super(…)或者this(….)必须出现在第一条语句
    否则,就会有父类数据的多次初始化

    所以一般建议任何类都提供无参构造

    继承中的方法

    子类与父类的方声明不一样,一般情况

    • 首先在子类中找
    • 然后在父类中找
    • 如果还是没有就报错。(不考虑多重继承)

    重写(Override)

    子类中出现了和父类中一模一样的方法声明,也被称为方法覆盖

    • 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法

    注意:

    1. 父类中私有方法不能被重写(子类写了相当于自己的创建方法,不算重写)

    2. 子类重写父类方法时,访问权限不能更低

    3. 父类静态方法,子类也必须通过静态方法进行重写。(不算是重写,但现象是这样)

       public class Fu {
           public static void pri() {
               System.out.println("a");
           }
       }
       //----------------------
       public class Zi extends Fu{         //This instance method cannot override the static method from Fu
           public void pri() {
               System.out.println("b");
           }
       }
      

    多态

    有继承关系
    有方法重写(没有方法重写的多态将没有意义)
    有父类引用指向子类对象
    

    多态中的成员访问特点:
    不能调用调用子类特有的属性和方法

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

    class Fu {
        public int num = 100;
    
        public void show() {
            System.out.println("show Fu");
        }
        
        public static void function() {
            System.out.println("function Fu");
        }
    }
    
    class Zi extends Fu {
        public int num = 1000;
        public int num2 = 200;
    
        public void show() {
            System.out.println("show Zi");
        }
        
        public void method() {
            System.out.println("method zi");
        }
        
        public static void function() {
            System.out.println("function Zi");
        }
    }
    
    class DuoTaiDemo {
        public static void main(String[] args) {
            //要有父类引用指向子类对象。
            //父 f =  new 子();
            Fu f = new Zi();
            System.out.println(f.num);
            //System.out.println(f.num2); //num2 cannot be resolved or is not a field(Fu中找不到num2)
            f.show();
            //f.method();   //The method method() is undefined for the type Fu(Fu中找不到method)
            f.function();
        }
    }   
    

    好处与弊端

    1. 多态的好处:
      • 提高了代码的维护性(继承保证)
      • 提高了代码的扩展性(由多态保证)
    2. 多态的弊端
      • 不能调用调用子类特有的属性和方法

    向上向下转型

    向上转型

    Fu f = new Zi();

    向下转型:把父类的引用强转为子类的引用

    Zi z = (Zi)f;

    多态继承中的内存图解

    B0iOfer.png

    多态中的对象变化内存图解

    1. 不可以访问子类的方法
    2. 不可以强转成其他子类(ClassCastException)
    image
    //ClassCastException
    DuoTaiDemo f1 = new Zi();
    DuoTaiDemo f2 = new DuoTaiDemo();
    DuoTaiDemo f3 = (Zi2)f1;
    DuoTaiDemo f4 = (Zi)f2;

    相关文章

      网友评论

          本文标题:面向对象

          本文链接:https://www.haomeiwen.com/subject/tvysnxtx.html