• java面向对象(封装,继承,多态,抽象,接口的定义和实现)


    1.封装

    •   在面向对象程式设计方法中,封装(英语:Encapsulation)是指,一种将抽象性函式接口的实作细节部份包装、隐藏起来的方法。
    •   封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
    •   要访问该类的代码和数据,必须通过严格的接口控制。
    •   封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。
    •   适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。

      实例:

    public class EncapTest{
    
       private String name;
       private String idNum;
       private int age;
    
       public int getAge(){
          return age;
       }
    
       public String getName(){
          return name;
       }
    
       public String getIdNum(){
          return idNum;
       }
    
       public void setAge( int newAge){
          age = newAge;
       }
    
       public void setName(String newName){
          name = newName;
       }
    
       public void setIdNum( String newId){
          idNum = newId;
       }
    }

     以上实例中public方法是外部类访问该类成员变量的入口。

    通常情况下,这些方法被称为getter和setter方法。

    因此,任何要访问类中私有成员变量的类都要通过这些getter和setter方法。

    通过如下的例子说明EncapTest类的变量怎样被访问:

    public class RunEncap{
    
       public static void main(String args[]){
          EncapTest encap = new EncapTest();
          encap.setName("James");
          encap.setAge(20);
          encap.setIdNum("12343ms");
    
          System.out.print("Name : " + encap.getName()+ 
                                 " Age : "+ encap.getAge());
        }
    }

     以上代码编译运行结果如下:

    Name : James Age : 20

    2.继承

    概念:

    继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。

    继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

    兔子和羊属于食草动物类,狮子和豹属于食肉动物类。

    食草动物和食肉动物又是属于动物类。

    所以继承需要符合的关系是:is-a,父类更通用,子类更具体。

    虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。

    类继承的格式:

    在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:

     

    class 父类 {
    }
     
    class 子类 extends 父类 {
    }

     为什么需要继承

    接下来我们通过实例来说明这个需求。

    开发动物类,其中动物分别为企鹅以及老鼠,要求如下:

    企鹅:属性(姓名,id),方法(吃,睡,自我介绍)

    老鼠:属性(姓名,id),方法(吃,睡,自我介绍)

    企鹅类

    public class Penguin { 
        private String name; 
        private int id; 
        public Penguin(String myName, int  myid) { 
            name = myName; 
            id = myid; 
        } 
        public void eat(){ 
            System.out.println(name+"正在吃"); 
        }
        public void sleep(){
            System.out.println(name+"正在睡");
        }
        public void introduction() { 
            System.out.println("大家好!我是"         + id + "号" + name + "."); 
        } 
    }

    老鼠类

    public class Mouse { 
        private String name; 
        private int id; 
        public Mouse(String myName, int  myid) { 
            name = myName; 
            id = myid; 
        } 
        public void eat(){ 
            System.out.println(name+"正在吃"); 
        }
        public void sleep(){
            System.out.println(name+"正在睡");
        }
        public void introduction() { 
            System.out.println("大家好!我是"         + id + "号" + name + "."); 
        } 
    }

     从这两段代码可以看出来,代码存在重复了,导致后果就是代码量大且臃肿,而且维护性不高(维护性主要是后期需要修改的时候,就需要修改很多的代码,容易出错),所以要从根本上解决这两段代码的问题,就需要继承,将两段代码中相同的部分提取出来组成 一个父类:

    public class Animal { 
        private String name;  
        private int id; 
        public Animal(String myName, int myid) { 
            name = myName; 
            id = myid;
        } 
        public void eat(){ 
            System.out.println(name+"正在吃"); 
        }
        public void sleep(){
            System.out.println(name+"正在睡");
        }
        public void introduction() { 
            System.out.println("大家好!我是"         + id + "号" + name + "."); 
        } 
    }

    这个Animal类就可以作为一个父类,然后企鹅类和老鼠类继承这个类之后,就具有父类当中的属性和方法,子类就不会存在重复的代码,维护性也提高,代码也更加简洁,提高代码的复用性(复用性主要是可以多次使用,不用再多次写同样的代码) 继承之后的代码:

    企鹅类

    public class Penguin extends Animal { 
        public Penguin(String myName, int myid) { 
            super(myName, myid); 
        } 
    }

     老鼠类

    public class Mouse extends Animal { 
        public Mouse(String myName, int myid) { 
            super(myName, myid); 
        } 
    }

    继承类型

    需要注意的是 Java 不支持多继承,但支持多重继承。

    继承的特性 

    • 子类拥有父类非 private 的属性、方法。
    • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
    • 子类可以用自己的方式实现父类的方法。
    • Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 A 类继承 B 类,B 类继承 C 类,所以按照关系就是 C 类是 B 类的父类,B 类是 A 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
    • 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。

    继承关键字

    继承可以使用 extends 和 implements 这两个关键字来实现继承,而且所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类。

    extends关键字

    在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。

    public class Animal { 
        private String name;   
        private int id; 
        public Animal(String myName, String myid) { 
            //初始化属性值
        } 
        public void eat() {  //吃东西方法的具体实现  } 
        public void sleep() { //睡觉方法的具体实现  } 
    } 
     
    public class Penguin  extends  Animal{ 
    }

    implements关键字

    使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)。

    public interface A {
        public void eat();
        public void sleep();
    }
     
    public interface B {
        public void show();
    }
     
    public class C implements A,B {
    }

    super 与 this 关键字

    super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。

    this关键字:指向自己的引用。

    class Animal {
      void eat() {
        System.out.println("animal : eat");
      }
    }
     
    class Dog extends Animal {
      void eat() {
        System.out.println("dog : eat");
      }
      void eatTest() {
        this.eat();   // this 调用自己的方法
        super.eat();  // super 调用父类方法
      }
    }
     
    public class Test {
      public static void main(String[] args) {
        Animal a = new Animal();
        a.eat();
        Dog d = new Dog();
        d.eatTest();
      }
    }

     输出结果为:

    animal : eat
    dog : eat
    animal : eat
    

     final关键字

    final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写:

    声明类:

    final class 类名 {//类体}

    声明方法:

    修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}
    :实例变量也可以被定义为 final,被定义为 final 的变量不能被修改。被声明为 final 类的方法自动地声明为 final,但是实例变量并不是 final

    构造器

    子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。

    如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。

     

    3.多态

    多态是同一个行为具有多个不同表现形式或形态的能力。

    多态就是同一个接口,使用不同的实例而执行不同操作,如图所示

    多态性是对象多种表现形式的体现。

     

     

    1 现实中,比如我们按下 F1 键这个动作:
    2 如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;
    3 如果当前在 Word 下弹出的就是 Word 帮助;
    4 在 Windows 下弹出的就是 Windows 帮助和支持。
    5 同一个事件发生在不同的对象上会产生不同的结果。

    多态的优点

    1. 消除类型之间的耦合关系

    2. 可替换性

    3. 可扩充性

    4. 接口性

    5. 灵活性

    6. 简化性

    多态存在的三个必要条件

    1. 继承
    2. 重写
    3. 父类引用指向子类对象

    父类引用指向子类对象

    子类重写父类方法

    父类引用调用子类重写后的方法

    执行结果:子类重写的方法

    比如:

    Parent p = new Child();

    当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。

    多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。

    以下是一个多态实例的演示,详细说明请看注释

    public class Test {
        public static void main(String[] args) {
          show(new Cat());  // 以 Cat 对象调用 show 方法
          show(new Dog());  // 以 Dog 对象调用 show 方法
                    
          Animal a = new Cat();  // 向上转型  
          a.eat();               // 调用的是 Cat 的 eat
          Cat c = (Cat)a;        // 向下转型  
          c.work();        // 调用的是 Cat 的 work
      }  
                
        public static void show(Animal a)  {
          a.eat();  
            // 类型判断
            if (a instanceof Cat)  {  // 猫做的事情 
                Cat c = (Cat)a;  
                c.work();  
            } else if (a instanceof Dog) { // 狗做的事情 
                Dog c = (Dog)a;  
                c.work();  
            }  
        }  
    }
     
    abstract class Animal {  
        abstract void eat();  
    }  
      
    class Cat extends Animal {  
        public void eat() {  
            System.out.println("吃鱼");  
        }  
        public void work() {  
            System.out.println("抓老鼠");  
        }  
    }  
      
    class Dog extends Animal {  
        public void eat() {  
            System.out.println("吃骨头");  
        }  
        public void work() {  
            System.out.println("看家");  
        }  
    }

    执行以上程序,输出结果为:

    吃鱼
    抓老鼠
    吃骨头
    看家
    吃鱼
    抓老鼠

    4.抽象

    4.1抽象(abstract)的使用

      当父类的某些方法不确定时,可以用abstract关键字来修饰该方法[抽象方法],用abstract来修饰该类[抽象类]。

      我们都知道,父类是将子类所共同拥有的属性和方法进行抽取,这些属性和方法中,有的是已经明确实现了的,有的还无法确定,那么我们就可以将其定义成抽象,在后日子类进行重用,进行具体化。这样,抽象类也就诞生了。

      例如,定义了“动物”父类,其中“动物名称”和“动物年龄”属性已经明确了,但是“动物叫”的方法没有明确,此时就可以将“动物叫”定义为抽象方法。

      所以,抽象类是为了把相同的但不确定的东西的提取出来,为了以后的重用。定义成抽象类的目的,就是为了在子类中实现抽象类。 

    package javastudy;
    
    public class AbstractDemo1 {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
    
        }
    }
    
    // 这就是一个抽象类
    abstract class Animal {
        String name;
        int age;
    
        // 动物会叫
        public abstract void cry(); // 不确定动物怎么叫的。定义成抽象方法,来解决父类方法的不确定性。抽象方法在父类中不能实现,所以没有函数体。但在后续在继承时,要具体实现此方法。
    }
    
    // 抽象类可以被继承
    // 当继承的父类是抽象类时,需要将抽象类中的所有抽象方法全部实现。
    class cat extends Animal {
        // 实现父类的cry抽象方法
        public void cry() {
            System.out.println("猫叫:");
    
        }
    }

    抽象总结规定

      • 1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。

      • 2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

      • 3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。

      • 4. 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。

      • 5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

      •         6.、一旦类中包含了abstract方法,那类该类必须声明为abstract类。

    5.接口的定义和实现

    5.1接口的定义

    使用interface来定义一个接口。接口定义同类的定义类似,也是分为接口的声明和接口体,其中接口体由常量定义和方法定义两部分组成。定义接口的基本格式如下:

    [修饰符] interface 接口名 [extends 父接口名列表]{

    [public] [static] [final] 常量;
    [public] [abstract] 方法;
    }
    修饰符:可选,用于指定接口的访问权限,可选值为public。如果省略则使用默认的访问权限。
    接口名:必选参数,用于指定接口的名称,接口名必须是合法的Java标识符。一般情况下,要求首字母大写。
    extends 父接口名列表:可选参数,用于指定要定义的接口继承于哪个父接口。当使用extends关键字时,父接口名为必选参数。
    方法:接口中的方法只有定义而没有被实现。

    例如,定义一个用于计算的接口,在该接口中定义了一个常量PI和两个方法,具体代码如下:

    1 public interface CalInterface   
    2 {  
    3     final float PI=3.14159f;//定义用于表示圆周率的常量PI  
    4     float getArea(float r);//定义一个用于计算面积的方法getArea()  
    5     float getCircumference(float r);//定义一个用于计算周长的方法getCircumference()  
    6 }

    5.2接口的实现

    接口在定义后,就可以在类中实现该接口。在类中实现接口可以使用关键字implements,其基本格式如下:
    [修饰符] class <类名> [extends 父类名] [implements 接口列表]{
    }
    修饰符:可选参数,用于指定类的访问权限,可选值为public、abstract和final。
    类名:必选参数,用于指定类的名称,类名必须是合法的Java标识符。一般情况下,要求首字母大写。
    extends 父类名:可选参数,用于指定要定义的类继承于哪个父类。当使用extends关键字时,父类名为必选参数。
    implements 接口列表:可选参数,用于指定该类实现的是哪些接口。当使用implements关键字时,接口列表为必选参数。当接口列表中存在多个接口名时,各个接口名之间使用逗号分隔。

    在类中实现接口时,方法的名字、返回值类型、参数的个数及类型必须与接口中的完全一致,并且必须实现接口中的所有方法。例如,编写一个名称为Cire的类,该类实现5.7.1节中定义的接口Calculate,具体代码如下:

    public class Cire implements CalInterface   
    {  
        public float getArea(float r)   
        {  
            float area=PI*r*r;//计算圆面积并赋值给变量area  
            return area;//返回计算后的圆面积  
        }  
        public float getCircumference(float r)   
        {  
            float circumference=2*PI*r;      //计算圆周长并赋值给变量circumference  
            return circumference;           //返回计算后的圆周长  
        }  
        public static void main(String[] args)   
        {  
            Cire c = new Cire();  
            float f = c.getArea(2.0f);  
            System.out.println(Float.toString(f));  
        }  
    }

    在类的继承中,只能做单重继承,而实现接口时,一次则可以实现多个接口,每个接口间使用逗号“,”分隔。

  • 相关阅读:
    Markdown编辑器语法指南2
    python文件读写的学习
    K:图相关的最小生成树(MST)
    K:哈弗曼树
    K:树、二叉树与森林之间的转换及其相关代码实现
    K:二叉树
    K:树与二叉树
    KandQ:那年,那树,那些知识点
    K:java中的安全模型(沙箱机制)
    K:java中的RMI(Remote Method Invocation)
  • 原文地址:https://www.cnblogs.com/songhuiqiang/p/10644165.html
Copyright © 2020-2023  润新知