黑马程序员——封装,继承与多态

 

------- android培训java培训、期待与您交流! ---------- 


面向对象的三个特征:封装,继承,多态。

封装:

封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式。即让对象的属性尽可能的私有,对象的方法尽可能的公开。避免外部对类的破坏。

 

好处:

1.提高安全性,避免不懂的人乱动,以保证安全。

2.提高重用性,可以多次使用。

3.隔离变化,变化的改变外界不会看见。

4.方便使用,不需要知道内部结构与原理就可以直接拿过来就能用。

 

实现方法:

private表示此成员属性为该类的私有属性(类内部可见)。其中私有只是封装的一种体现。

相反:

Public表示该属性(方法)公开;

 

所以想用private的属性时候,要对属性进行set和get方法的实现以供其他方法调用,这样可以保证对属性的访问方式统一,并且便于维护访问权限以及属性数据合法性。

 

class Person
{
      private int age; //私有的属性
 
      public void setAge(int a)//共有的方法去处理私有的属性,通过:setXxx getXxx
      {
            age = a;
      }
      public int getAge()
      {
            return  age;
      }
}

 

继承:

继承:因为有些类具有相同属性和行为,把这些相同的内容抽取到单独一个类中,那么其余就无需再定

         义这些属性和行为,而只需要继承单独的那个类即可。继承的类称为子类,被继承的类称为父类

         超类。

 

其中子类可以通过extends 关键字让本类与父类之间产生继承关系,从而子类可以直接访问父类中的非私有的属性和行为。

         代码中的体现为:class 子类名 extends 父类名

{

类内部

}

 

好处:
1,提高了代码的复用性,使代码可以重复使用。
2,让类与类之间产生了关系。这关系形成了java多态的特性。

 

类与类之间所属关系为:is a,即判断是否要用继承,只需要看:榕树是树:即榕树可以继承树的特性;

  兔子的动物:即兔子可以继承动物的特性;

相反:树不一定是榕树,所以树不能继承榕树。

3,java支持多层继承,形成了继承体系。使用一个继承体系中的功能时,应该先查阅体系父类的描述了解体系中的共性功能;但是在具体调用时,要创建最子类的对象,因为父类可能是抽象类不能被创建对象或者父类不具有子类特有的方法,而非抽象最子类能创建对象且具有共性和特有方法。

 

缺点:

1,java只支持单继承,不支持多继承。因为多继承会带来安全隐患:当子类继承多个父类,而不同父类中可能有同名不同功能方法时,子类调用他们的方法就会出现无法选择的结果,导致编译不成功。但是java可以通过实现多个接口,即多实现,来达到“多继承”的目的。

2,破坏了封装性,因为通过继承可以使用和更改类内部,所以final关键字可以避免被继承。

 

覆盖:

当子类继承父类时子类就沿袭了父类的功能,然而在子类中子类虽然具备该功能,但是功能的内容却和父类可能不一致。这时,没有必要定义新功能,而是使用覆盖来保留父类的功能定义并重写功能的内容。

 

注意

1,子类覆盖父类时要保证子类权限大于等于父类权限,否则编译失败。即父类类为defoult,那么子类只能时public或defoult。

2,静态只能覆盖静态。

 

public class Person 
{
      Person()
      {
            System.out.println("Person的构造函数");
      }
      
      Person(int age)
      {
            System.out.println("Person的有参数构造函数");
      }
 
      public void playToy()
      {
            System.out.println("Person的方法");
      }
 
      
      public void cry()
      {
            System.out.println("Person的哭方法");
      }
}
public class Student extends Person //继承
{
      Student()
      {
            System.out.println("Student的空参数构造函数");
      }
      
      Student(int age)
      {
            super(age);
            System.out.println("Student的有参数构造函数");
      }
 
      //具有playToy的方法。
 
      public void cry() //覆盖,对父类的方法进行了改变。
      {
            playToy();
                  System.out.println("Student的哭方法");
      }    
}

 

重载与重写的区别:

重载:针对构造函数而言,其中参数列表不同,方法体不同,其余都一样。

重写:针对继承类中的成员函数而言,子父类一模一样,除了方法体的内容。


注意:因为子类对象在建立时,需要先查看父类是如何对数据进行初始化的,所以子类的构造函数默认第一行有一条隐式的语句 super(),因此在对子类对象进行初始化时,父类的构造函数也会运行。

 

super关键字

1.super和this的用法一样,super.num = '' 3'';

2.super代表父类的引用。

3.当子父类出现同名成员时,可以用super进行区分,在子类中用super来替代名字。

4.子类要调用父类构造函数时,可以使用super语句。

5.super():是访问父类中空参数的构造函数,每个子类必有一个构造函数中有第一行默认为或显式有super()来访问父类。

 

final关键字

final : 最终的意思,是一个修饰符

来修饰类

,使

别人就不能继承此类;修饰功能(方法),使被修饰的方法不能被覆盖,修饰变量使之成为不可变的常量。

 

ex:

final常量,

如:public static final double PI =3.14;

 

注意:

内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。

 

抽象:即不具体的东西,如树为抽象,榕树为具体;动物为抽象,人为具体。

抽象类:Java中定义的没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类,被abstract关键字修饰。也因此抽象方法一定在抽象类中。

 

对于抽象方法,只有方法声明,没有方法体:abstract voidrunTo(){}

 

注意:抽象类不可以用new创建对象。因为调用抽象方法没实现的功能,所以没有意义去创建他们的对象。只有当抽象类中的抽象方法由子类全部复写后,才能建立子类对象实现功能的调用。如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。其中抽象类中可以有非抽象方法,妨碍抽象方法会被子类继承后调用。

 

abstract 与final,private和static不能共存:

private: 子类不能知道父类的抽象方法,因此就无法被复写。

final:final修饰的类不能有子类,abstract修饰的类必须要有子类来实现内部功能。

static:static修饰的方法不需要对象就可以调用,调用无方法体的抽象方法无意义。

 

接口:当抽象类中的方法都是抽象的,那么该类就时接口,用interface用来定义。因此,接口是不可以创建对象的,只有子类对接口中的抽象方法全都覆盖后,子类才可以实例化。否则子类就是一个抽象类。

 

接口格式为 :  interface 接口名 {}           比较:类的格式为:class 类名字(){}

接口中常量和抽象函数的默认表达方式为:

常量:public static final

方法:public abstract 

 

好处:

1.对外暴露了规则,从而其他类可以参阅并实现。

2.降低耦合度,降低了类与类的关系复杂度。

3.因此,接口帮助实现了程序的功能扩展。

4.类与接口之间是实现关系,而且类继承类的同时可以多实现接口(因为接口中方法没有方法主体,所以接口之间可以继承)。达到“多继承”的效果。

5.接口与接口之间有继承关系,并且可以多继承。

 

接口与抽象类:

1,共同点:

2,都不能实例化;

3,都位于继承的顶端,包含抽象方法,所以子类都必须覆写(实现或继承)这些抽象方法;

 

不同点:

1,抽象类可以有非抽象方法;

2,接口只能包含抽象方法;

3,一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;

 

所以,编程应该优先选用接口,而少用抽象类。只有在需要定义子类与父类既有继承关系(is a)的时候,又不能完全实现某些函数功能的时候才选用抽象类。

 

Eg:

interface Car
{
      void run();
      void door();
}

class miniCar implementsCar

{

  @Override

  public voidrun() { }

  @Override

  public voiddoor() { }

 }

 

class MyCar extends miniCar

{

  public voiddoor(){

     System.out.println("我的开关门功能!");  //覆写父类的方法

  }

}

 

public class Demo 

{

  public staticvoid main(String[] args) 

      {

                   newMyCar().door();

   }

}

 

 

多态


多态:当子类继承父类时或者一个类实现某个接口时,此子类(实现类)就有多种体现出来的形态。

 

比如 猫是猫本身的同时还时只哺乳动物,同时也是只动物。


多态体现在两方面:
父类的引用指向了自己的子类对象。动物动物的引用= 子类;
父类的引用也可以接收自己的子类对象。(动物的引用子类)

优点:提高程序的扩展性。


弊端:只能使用父类的引用访问父类中的成员,而不能访问子类的成员。

 


出现的原因:编译时的类型由声明该变量时使用的类型决定,而在运行的时候,运行类型由实际赋给变量的对象决定。

如果编译时类型和运行时类型不同,就出现多态。所以,在分析多态时要:

对应成员函数:编译看左边运行看右边

对应成员变量:无论编译还是运行都看左边 

对应静态成员函数:编译或运行都看左边 

 

Eg:

有:miniCar extends  Car:         即:继承或实现是多态产生的前提条件

 

Car p= new Car();

miniCar s = new miniCar();

Car p= new miniCar();//多态

 

class Dog{
      void eat(){
            System.out.println("一般的狗吃一般的狗粮!");
      }
}
 
class HashDog extends Dog{
      void eat(){
            System.out.println("哈士奇吃哈士奇的狗粮!");
      }
}
 
class ZangAoDog extends Dog{
      void eat(){
            System.out.println("藏獒吃藏獒的狗粮!");
      }
}
 
//定义的在动物园喂食物的方法
class Zoo{
      
      void feed(Dog d){
            d.eat();
      }
      
}
//例子
public class Demo11
{
      public static void main(String[] args) 
            {           
            Dog zd = new ZangAoDog();
 Dog hd = new HashDog();Zoo z = new Zoo();输出:z.feed(hd); //哈士奇吃哈士奇的狗粮
            z.feed(zd);                  //藏獒吃藏獒的狗粮
}}
在多态运用时,经常涉及类的检验,用  对象名  instanceof  类  来判断指定的变量名此时引用的真正类型是不是当前给出的类或子类;

Eg:

class miniCar extends Car
{
      Car b = new miniCar();
      If(Car instanceof miniCar)
      {    }
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值