Java07-面向对象高级特性

第7章面向对象高级性特性

第7章 面向对象高级特性导航
 7.1 继承
  7.1.1 继承的特性
  7.1.2 继承的关键词
  7.1.3 Extends关键词
  7.1.4 Implement关键词
  7.1.5 super与this关键词
  7.1.6 sinal关键词
  7.1.7 构造器
  7.1.8 总结
 7.2 封装
  7.2.1 封装的概念
  7.2.2 封装的实现步骤
  7.2.3 Java中的包
  7.2.4 包的使用
  7.2.5 java中的访问修饰符
  7.2.6 java中的this关键字
 7.3 抽象类和接口
  7.3.1 abstract和final
  7.3.2 接口
 7.4 多态
 7.5 内部类
  7.5.1 内部类
  7.5.2 内部类之成员内部类
  7.5.3 静态内部类
  7.5.4 方法内部类
 7.6 类与类之间的关系
  7.6.1 继承(is-a)
  7.6.2 实现
  7.6.3 依赖(uses-a)
  7.6.4 关联
  7.6.5 聚合(has-a)
  7.6.6 组合(contains-a)

7.1继承

7.1.1继承的特性

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

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

7.1.3Extends关键词
  在 Java 中,类的继承是单一继承。即一个子类只能有一个父类,但一个父类可以有多个子类。语法为:class 子类 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{ 
    }

7.1.4Implement关键词
  使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)
  接口仅包含方法定义和常量值。

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

7.1.5Super与this关键词
  super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
  this关键字:指向自己的引用。
  实例:

     public class SuperDemo {
    public static void main(String []args) {
        new SubClass().showMessage();
    }
}
 
class SuperClass {
    int i = 50;
}
 
class SubClass extends SuperClass {
    int i =100;
    public void showMessage() {
        System.out.printf("super.i = %d, this.i = %d\n", super.i, this.i);
    }
}

  输出结果:super.i = 50, this.i = 100

7.1.6final关键词
  final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写:
  声明类
  final class 类名 {//类体}
  声明方法
  修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}
  注:实例变量也可以被定义为 final,被定义为 final 的变量不能被修改。被声明为 final 类的方法自动地声明为 final,但是实例变量并不是 final

7.1.7构造器
  子类不能继承父类的构造器(构造方法或者构造函数),但是父类的构造器带有参数的,则必须在子类的构造器中显式地通过super关键字调用父类的构造器并配以适当的参数列表。
  如果父类有无参构造器,则在子类的构造器中用super调用父类构造器不是必须的,如果没有使用super关键字,系统会自动调用父类的无参构造器。
  实例

 class SuperClass {
   private int n;
   SuperClass(){
     System.out.println("SuperClass()");
   }
   SuperClass(int n) {
     System.out.println("SuperClass(int n)");
     this.n = n;
   }
 }
 class SubClass extends SuperClass{
   private int n;
   
   SubClass(){
     super(300);
     System.out.println("SubClass");
   }  
   
   public SubClass(int n){
     System.out.println("SubClass(int n):"+n);
     this.n = n;
   }
 }
 public class TestSuperSub{
   public static void main (String args[]){
     SubClass sc = new SubClass();
     SubClass sc2 = new SubClass(200); 
   }
 }

  结果:SuperClass(int n)
  SubClass
  SuperClass()
  SubClass(int n):200

7.1.8总结
  1、为什么使用继承?
  从已有的类派生出新的类,称为继承。
  在不同的类中也可能会有共同的特征和动作,可以把这些共同的特征和动作放在一个类中,让其它类共享。因此可以定义一个通用类,然后将其扩展为其它多个特定类,这些特定类继承通用类中的特征和动作。
  继承是 Java 中实现软件重用的重要手段,避免重复,易于维护,易于理解。
  2、父类和子类
  如果类 B 从类 A 派生,或者说类 B 扩展自类 A,或者说类 B 继承类 A,则称类 A 为"父类",也称为超类、基类;称类 B 为"子类",也称为次类、扩展类、派生类。
  子类从它的父类中继承可访问的数据域和方法,也可以添加新的数据域和新的方法。

  定义继承的语法
  修饰符 class 子类名 extends 父类名
  例如:Shape 类是父类,其子类可以有 Circle 类、Rectangle 类、Triangle 类,等等。
  继承的注意点

  • 子类不是父类的子集,子类一般比父类包含更多的数据域和方法。
  • 父类中的 private 数据域在子类中是不可见的,因此在子类中不能直接使用它们。
  • 继承是为"是一个"的关系建模的,父类和其子类间必须存在"是一个"的关系,否则不能用继承。但也并不是所有"是一个"的关系都应该用继承。例如,正方形是一个矩形,但不能让
    Square 类来继承 Rectangle 类,因为正方形不能从矩形扩展得到任何东西。正确的继承关系是 Square 类继承 Shape
  • Java 只允许单一继承(即一个子类只能有一个直接父类),C++ 可以多重继承(即一个子类有多个直接父类)。

  3、super 关键字
  super 表示使用它的类的父类。super 可用于:

  1. 调用父类的构造方法;
  2. 调用父类的方法(子类覆盖了父类的方法时);
  3. 访问父类的数据域(可以这样用但没有必要这样用)。
  4. 调用父类的构造方法语法:

  super();或super(参数列表);
  注意:super 语句必须是子类构造方法的第一条语句。不能在子类中使用父类构造方法名来调用父类构造方法。 父类的构造方法不被子类继承。调用父类的构造方法的唯一途径是使用 super 关键字,如果子类中没显式调用,则编译器自动将 super(); 作为子类构造方法的第一条语句。这会形成一个构造方法链。
  静态方法中不能使用 super 关键字。

  调用父类的方法语法:
  super.方法名(参数列表);
  如果是继承的方法,是没有必要使用 super 来调用,直接即可调用。但如果子类覆盖或重写了父类的方法,则只有使用 super 才能在子类中调用父类中的被重写的方法。
  4、this 关键字
  this 关键字表示当前对象。可用于:

  • 调用当前类的构造方法,并且必须是方法的第一条语句。如:this(); 调用默认构造方法。this(参数); 调用带参构造方法。
  • 限定当前对象的数据域变量。一般用于方法内的局部变量与对象的数据域变量同名的情况。如 this.num = num。this.num
    表示当前对象的数据域变量 num,而 num 表示方法中的局部变量。

7.2封装

7.2.1封装的概念
  将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来对隐藏的信息进行操作和访问。
  好处
  (1)只能通过规定的方法访问数据
  (2)隐藏类的实例细节,方便修改和实现。
7.2.2封装的实现步骤
  (1)修改属性的可见性设为(private)
  (2)创建getter/setter方法(用于属性的读写)(通过这两种方法对数据进行获取和设定,对象通过调用这两种发方法实现对数据的读写)
  (3)在getter/setter方法中加入属性控制语句(对属性值的合法性进行判断)
7.2.3Java中的包
  (1)作用:管理java文件,解决同名文件的冲突
  (2)定义包:package 包名必须放在java源程序的第一行,包名间可以使用“.”号隔开例如:com.imooc.Myclass
7.2.4包的使用

  • 可以通过import关键字,在某个文件中使用其他文件中的类。import.com.imooc.music.MyClass
  • java中,包的名字规范是全小写的字母拼写
  • 使用时,不仅可以加载某个包下的所有文件 比如:com.imooc.* 也可以加载某个具体子包下的所有文件
    比如:com.imooc.music.*

7.2.5java中的访问修饰符
  private:只能在本类中使用(正因为private中的元素不能在外面直接访问,所以才利用调用getter/setter方法访问)
默认:本来和同包中使用
  protected:本类,同包,子类中使用
  public:本类,同包,子类,其他中都可以使用

7.2.6java中的this关键字
  this关键字代表当前对象this.
  属性:操作当前对象的属性this.
  方法:调用当前对象的方法,封装对象的属性的时候经常会使用this关键字
  例如:

private float screen;
public void setScreen(float screen){
     this.screen=screen;     //因为参数和属性值一样了,所以用this.scree分清参数和属性}

7.3抽象类和接口
  1、类和接口都不能直接实例化。如果要实例化,涉及到多态。抽象类要实例化,抽象类定义的变量必须指向一个子类变量,这个子类继承并实现了抽象类所有的抽象方法。接口要实例化,接口定义的变量必须指向一个子类变量,这个子类继承并实现了接口所有的方法。
  2、抽象要被子类继承,接口要被子类实现
  3、接口里只能对方法进行声明,抽象类里既可以对方法进行声明,又可以实现。
  4、抽象类里面的抽象方法必须被子类实现,如果子类不能全部实现,子类必须也是抽象类。接口里面的方法必须被子类实现,如果子类不能全部实现,子类必须是抽象类
  6、抽象类里面可以没有抽象方法,如果一个类里面有抽象方法,那么这个类一定是抽象类。
  7、抽象类中的抽象方法都要被实现,所以抽象方法不能是静态的static,也不能是私有的private
  8、接口可以继承接口,甚至可以继承多个接口;类可以实现多个接口,只能继承一个类。

  额外:
  接口与抽象类是不同的概念。抽象类时用于捕捉子类的通用特性,接口是抽象方法的集合。
  实现接口必须实现接口的所有方法。
  接口可以继承一个或多个接口,抽象类只能继承一个类或实现多个接口
  一个类只能继承一个类,但是可以实现多个接口

7.3.1abstract和final
  abstract
  1.类里面包含有抽象方法,则这个类必须是抽象类;但抽象类不一定包含抽象方法。抽象类中,可以同时包含抽象方法和非抽象方法;
  2.使用abstract修饰的方法叫抽象方法,抽象方法没有方法体{};格式为:修饰符 abstract 返回值类型 方法名(参数列表);–没有方法体
  3.抽象类不能使用new进行实例化,但可以通过非抽象子类进行实例化调用
  4.子类必须实现或重写父类定义的抽象方法: 即当需要子类重写或实现方式时,可以把特定的方法声明为抽象方法。
  5.一个子类继承了一个抽象类,也会继承该父类的抽象方法,如果父类包含有抽象方法,则子类必须实现该抽象方法(子类意识抽象类除外)。
  6.对于abstract的子类来说有两种途径:一种是实现其超类的所有abstract方法;一种是子类也声明为abstract类,将全部实现方法的责任交给它的子类
  7.抽象方法不能使用private进行修饰,可使用public,default,protected访问修饰符修饰
  8.抽象方法不能使用static和final关键词修饰,final修饰的方法不能重写,不能有子类。
  例1:抽象类:public abstract class AbstractClass {类主体}
  例2:抽象方法:public abstract void absMethod();
  例3:通过非抽象子类调用抽象类:

public static void main(String[] args) {
		//抽象类不能使用new进行实例化
		//AbstractClass b = new AbstractClass();
		//抽象类一般由非抽象的子类进行实例化,多态编程
		AbstractClass b = new SubAbstractClass();
		b.absMethod();
		b.sex();
		b.Message(2, 3, "女");
	}

  非抽象子类为:

public class SubAbstractClass extends AbstractClass{
	//在非抽象的子类中重写方法
	public void absMethod(){
		System.out.println("非抽象方法");
	}
	public void absM(int id,int name ,String sex){
		System.out.print(id+","+name+","+sex);
	}
}

  final

  1. 使用final修饰的方法称为终结方法,终结方法不能被重写。
  2. abstract和final不能同时修饰类。
  3. final不能被继承,不能有子类。
  4. abstract修饰的类中可以有final子类。

  例4:

public final void print(){
System.out.println(“打印”);
}

  补充:
  属性常量需要在定义时进行初始化,常量一旦被初始化就不能被修改。属性常量如果在定义时没有进行初始化,可以在构造方法中初始化一次。类属性(使用static修饰)必须在定义时初始化,一旦被初始化,则不能被修改。
  例:

public AbstractClass() {
		super();
		this.sex = "男";
	}

7.3.2接口
  一个类可以实现多个接口,实现接口使用implements关键词。语法为:class 类名 implements 接口名{类主体};
  一个类实现多个接口,需要实现(重写)接口的所有方法,同时也可以实现一个负接口和它的子接口,同时集成一个父类实现一个或多个接口。
  接口定义的都是常量,必须在定义时初始化,其默认的修饰符是public,static,final;修饰符的位置可颠倒,但数据类型一定要在常量名或变量名前面
  一个接口能继承多个父接口–多继承,但接口不能实现接口。接口继承多个接口后,会继承接口的多个方法和接口常量。接口常称为接口规范,它约束了接口的实现类必须实现特定(接口约定)的方法。
  多继承接口:可以一个或多个接口。
  例1:接口与接口常量案例

public interface IFly {
	//接口定义的都是常量,必须在定义时初始化。
	public static final String WINGS = "翅膀";
	String WINGS2 = "翅膀2";
	static public final String WINGS3 = "翅膀3";
	//接口方法不能包含有方法体,接口方法都是抽象方法
	//接口方法默认abstract,public修饰,可写可不写
	public void fly();
	//特例在jdk1.8以上的版本,可以使用default关键词在接口中添加默认的方法实现
	public default void sing(){
	}
}

  例2:接口的继承

public interface IAnimal extends IFly,IRun,ISwim{
	void breath();
}

7.4多态

  Java的多态性主要表现在方法重载、方法覆盖和变量覆盖三个方面。
  多态定义:是同一操作(方法)作用于不同的对象时,可以有不同的解释,产生不同的执行结果。
  多态:父类调用子类的方法。
  在继承编程中,可以把子类对象直接赋值给父类对象,会进行类型的自动转换。
  用法:在父类写一个虚方法或抽象方法,子类去重写父类的方法,在调用的时候系统根据对象运行时的类型决定调用哪个方法。

7.5内部类

7.5.1内部类
  (1)定义:内部类( Inner Class )就是定义在另外一个类里面的类。与之对应,包含内部类的类被称为外部类。
  (2)作用:内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。
  内部类的方法可以直接访问外部类的所有数据,包括私有的数据
  内部类所实现的功能使用外部类同样可以实现,只是有时使用内部类更方便
  (3)分类:
  成员内部类
  静态内部类
  方法内部类
  匿名内部类
  例如:
在这里插入图片描述

public class InnerClass {
	public class Inner{
		public void show(){
			System.out.println("welcome");
		}
	}public static void main(String[] args) {
		InnerClass s = new InnerClass();
		Inner i = s.new Inner();
		i.show();
	}
}									

  注意内部类对象的创建。

7.5.2内部类之成员内部类
  定义:定义在一个类中的类似于这个类的一个成员变量的内部类成为***成员内部类***
  成员内部类的使用方法:例如:

  (1) Inner 类定义在 Outer 类的内部,相当于 Outer 类的一个成员变量的位置,Inner 类可以使用任意访问控制符,如 public 、 protected 、 private 等
  (2) Inner 类中定义的 test() 方法可以直接访问 Outer 类中的数据,而不受访问控制符的影响,如直接访问 Outer 类中的私有属性;
  (3) 定义了成员内部类后,必须使用外部类对象来创建内部类对象,而不能直接去 new 一个内部类对象,即:内部类 对象名 = 外部类对象.new 内部类( );
  (4) 编译上面的程序后,会发现产生了两个 .class 文件 其中,第二个是外部类的 .class 文件,第一个是内部类的 .class 文件,即成员内部类的 .class 文件总是这样:外部类名$内部类名.class;
  (5)外部类是不能直接调用内部类的变量和方法的,可先创建内部类的对象,然后通过内部类的对象来访问其成员变量和方法;
  (6)如果外部类和内部类具有相同的成员变量或方法,内部类默认访问自己的成员变量或方法,如果要访问外部类的成员变量,可以使用 this 关键字。如:
在这里插入图片描述

7.5.3静态内部类
  定义:被static修饰的内部类成为静态内部类
  使用方法:
  (1)静态内部类不能直接访问外部类的非静态成员,但可以通过 new 外部类().成员 的方式访问
  (2)如果外部类的静态成员与内部类的成员名称相同,可通过***“类名.静态成员”访问外部类的静态成员***(这里和成员内部类是不同的,成员内部类是通过类名.this.变量名来调用的);如果外部类的静态成员与内部类的成员名称不相同,则可通过“成员名”直接调用外部类的静态成员
  (3) 创建静态内部类的对象时,不需要外部类的对象,可以直接创建 内部类 对象名= new 内部类();

7.5.4方法内部类
  定义:方法内部类就是内部类定义在外部类的方法中,方法内部类只在该方法的内部可见,即只在该方法内可以使用。例如:
在这里插入图片描述
  注意:
  (1)因为是方法内部类不能被除了方法之外所使用,所以不能直接mo.print().应该是mo.show().因为这个内部类是定义在show这个方法中的。
  (2)由于方法内部类不能在外部类的方法以外的地方使用,因此方法内部类不能使用访问控制符和 static 修饰符。

7.2.12、总结:
  (1)只有是成员内部类创建内部类对象时候才需要通过外部类对象来创建。其他都是可以直接创建的。
  (2)当外部类和内部类变量重名的话,想要调用外部变量。成员内部类需要(类名.this.变量名)。静态内部类需要是(类名.变量名)

7.6类与类之间的关系

7.6.1继承(is-a)
  指的是一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,并可以增加它自己的新功能的能力,继承是类与类或者接口与接口之间最常见的关系;在Java中此类关系通过关键字extends明确标识。

7.6.2实现
  指的是一个class类实现interface接口(可以是多个)的功能;实现是类与接口之间最常见的关系;在Java中此类关系通过关键字implements明确标识。

7.6.3依赖(uses-a)
  是类与类之间的连接,表示一个类依赖于另一个类的定义,其中一个类的变化将影响另外一个类。例如如果A依赖于B,则B体现为局部变量,方法的参数、或静态方法的调用。
  某个类以局部变量的形式出现在另一个类中,二者是依赖关系。

7.6.4关联
  类与类之间的联接,它使一个类知道另一个类的属性和方法。例如如果A关联于B,则B体现为A的全局变量。
  关联关系有双向关联和单向关联:
  双向关联:两个类相互都知道另一个类的公共属性和操作。
  单向关联:只有一个类知道另外一个类的公共属性和操作。
  大多数关联应该是单向的,单向关系更容易建立和维护,有助于寻找可服用的类。
  某个类以成员变量的形式出现在另一个类中,二者是关联关系。

7.6.5聚合(has-a)
  整体与部分之间是可分离的,他们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享;比如计算机与CPU、公司与员工的关系等;表现在代码层面,和关联关系是一致的,只能从语义级别来区分。

7.6.6组合(contains-a)
  体现整体与部分间的关系,但此时整体与部分是不可分的,整体的生命周期结束也就意味着部分的生命周期结束;比如你和你的大脑;表现在代码层面,和关联关系是一致的,只能从语义级别来区分。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值