Java中的继承、封装、多态的理解

Java中的继承、封装、多态

继承的理解:

1、继承是面向对象的三大特征之一,也是实现代码复用的重要手段。Java的继承具有单继承的特点,每个子类只有一个直接父类。

2、Java的继承通过extends关键字来实现,实现继承的类被称为子类,被继承的类称为父类(有的也称其为基类、超类),父类和子类的关系,是一种一般和特殊的关系。就像是水果和苹果的关系,苹果继承了水果,苹果是水果的子类,水果是苹果的父类,则苹果是一种特殊的水果。

3、Java使用extends作为继承的关键字,extends关键字在英文是扩展的意思,而不是继承。为什么国内把extends翻译成继承呢?除了与历史原因有关外,把extends翻译成为继承也是有其道理的:子类扩展父类,将可以获得父类的全部属性和方法,这与汉语中得继承(子辈从父辈那里获得一笔财富成为继承)具有很好的类似性。值得指出的是:Java的子类不能获得父类的构造器。

4、实例:

class BaseClass{

public double weight;

public void info() {

System.out.println("我的体重是"+weight+"千克");

}

}

public class ExtendsDemo001 extends BaseClass {

public static void main(String[] args) {

//创建ExtendsDemo001对象

ExtendsDemo001 ed = new ExtendsDemo001();

//ExtendsDemo001本身没有weight属性,但是ExtendsDemo001的父类有weight属性,也可以访问ExtendsDemo001对象的属性

ed.weight = 56;

//调用ExtendsDemo001对象的info()方法

ed.info();

}

}

打印结果为:我的体重是56.0千克

5、Java类只能有一个父类。这句话是错误的,应该这样说:Java类只能有一个直接父类,可以有无限多个间接父类,如:

class  Fruit  extends  Plant{…….}

class  Apple  extends  Fruit {…….}

重写父类的方法:

1、  大部分的时候,子类总是以父类为基础,额外添加新的属性和方法。但有一种情况例外:子类需要重写父类的方法。例如鸟类都包含了飞翔的方法,其中鸵鸟是一种特殊的鸟类,因此鸵鸟也是鸟的子类,因此它也将从鸟类获得飞翔方法,但这个飞翔方法明显不适合鸵鸟,为此,鸵鸟需要重写鸟类的方法。

2、  如下代码可以帮助理解重写:

1)  class Bird{

2)  //Bird类的fly()方法

3)  private void fly(){

4)      System.out.println("我要在天空中飞翔");

5)  }

6)  }

7)  public class OcerrideTest extends Bird{

8)  //重写Bird类的fly()方法

9)  public void fly(){

10)    System.out.println("我只能在地上奔跑");

11) }

12) public static void main(String[] args) {

13)    //创建OcerrideTest对象

14)    OcerrideTest ot = new OcerrideTest();

15)    ot.fly();

16) }

17)   }

打印结果为:我只能在地上奔跑

这种子类包含父类同名方法的现象被称为方法重写,也被称为方法覆盖(Override)。

方法的重写要遵循“两同两小一大”规则:

⑴     “两同”:方法名相同;形参列表相同。

⑵     “两小”:子类方法之返回类型应比父类方法返回值类型更小或相等;子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等。

⑶     子类方法的访问权限应比父类方法更大或相等

尤其需要指出的是:覆盖方法和被覆盖方法要么都是类方法,要么都是实例方法,不能一个是类方法,一个是实例方法,例如下面的代码将会有编译错误:

Class  BaseClass{

public  static  void  test(){…….}

}

Class  SubClass extends BaseClass{

public void test(){………….}

}

若想调用父类中的fly()方法,则只需在子类中fly()方法中加上如下代码即可:

super.fly();

注意:super和this一样,都不能出现在static的方法中

调用父类构造器

1、看如下程序定义的Basehe Sub类,其中Sub类是Base类的子类,程序在Sub类的构造器中使用super来调用Base构造器里的初始化代码。

class Base{

public double size;

public String name;

public Base(double size, String name){

this.size=size;

this.name=name;

}

}

public class Sub extends Base{

public String color;

public Sub(double size, String name, String color){

//在子类构造器中调用父类构造器,使用super调用来实现

super(size,name);

this.color = color;

}

public static void main(String[] args) {

Sub s = new Sub(5.6,"测试对象","红色");

System.out.println(s.size+"------"+s.name+"------"+s.color);

}

}

打印结果为:5.6------测试对象------红色

静态初始化块

1、如果定义初始化块时使用了static修饰符,则这个初始化块,就变成了静态初始化块,也被称作为类初始化块。静态初始化块是类相关的,系统将在类初始化阶段执行静态初始化块,而不是在创建对象时才执行。因此静态初始化块总是比普通初始化块先执行

封装的理解:

1、封装(Encapsulation)是面向对象的三大特征之一,它指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。

2、掌握了访问控制符的用法之后,下面通过使用合理的访问控制来定义一个Person类,这个Person类就实现了良好的封装。代码如下:

public class Person {

public static void main(String[] args) {

Person p = new Person();

p.setAge(10);

System.out.println(p.getAge());

}

//将属性使用private修饰,将这些属性隐藏起来

private String name;

private int age;

//提供方法来操作name属性

public void setName(String name) {

//对姓名执行合理的校验

if(name.length() > 6 || name.length() < 2){

System.out.println("您的姓名不符合要求");

}else{

this.name = name;

}

}

public String getName() {

return this.name;

}

//提供方法来操作age属性

public void setAge(int age) {

if(age>100 || age<0){

System.out.println("您的年龄必须要在0~100之间");

}else{

this.age = age;

}

}

public int getAge() {

return this.age;

}

}

运行结果为:10

多态的理解:

1、多态(Polymorphism)是面向对象的三大特征之一。

2、Java引用变量有两个类型:一个是编译时类型,一个是运行时类型。编译时的类型由声明该变量时使用的类型决定,运行时的类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就会出现所谓的多态(Polymorphism

先看下面的程序:

class SuperClass{

public int book = 6;

public void base() {

System.out.println("父类的普通方法base()");

}

public void test(){

System.out.println("父类中北覆盖的方法");

}

}

public class PloymorphismTest001 extends SuperClass{

//重新定义一个book实例属性,覆盖父类的book实例属性

public String book = "Java疯狂讲义";

public void test() {

System.out.println("子类中覆盖父类的方法");

}

private void Dmeo() {

System.out.println("子类中普通的方法");

}

//主方法

public static void main(String[] args) {

//下面编译时类型和运行时类型完全一样,因此不存在多态

SuperClass sc = new SuperClass();

System.out.println("book1= "+sc.book);//打印结果为:6

//下面两次调用将执行SuperClass的方法

sc.base();

sc.test();

//下面编译时类型和运行时类型完全一样,因此不存在多态

PloymorphismTest001 pt = new PloymorphismTest001();

System.out.println("book2= "+pt.book);//打印结果为:Java疯狂讲义

//下面调用将执行从父类继承到的base方法

pt.base();

//下面调用将执行当前类的test方法

pt.test();

//下面编译时类型和运行时类型不一样,多态发生

SuperClass sscc = new PloymorphismTest001();

//结果表明访问的是父类属性

System.out.println("book3= "+sscc.book);//打印结果为:6

//下面调用将执行从父类继承到得base方法

sscc.base();

//下面调用将执行当前类的test方法

sscc.test();

//因为sscc的编译类型是SuperClass,SuperClass类没有提供Demo()方法

//所以下面代码编译时会出现错误

//sscc.Demo();

}

}

程序运行结果为:

book1= 6

父类的普通方法base()

父类中北覆盖的方法

book2= Java疯狂讲义

父类的普通方法base()

子类中覆盖父类的方法

book3= 6

父类的普通方法base()

子类中覆盖父类的方法

上面程序的main方法中显示创建而来3个引用变量,对于前两个引用变量sc和pt,它们编译时类型和运行时类型完全相同,因此调用它们的属性和方法非常正常,完全没有问题。但第三个引用变量sscc,则比较特殊,它编译时类型是SuperClass ,而运行时类型是PloymorphismTest001,当调用该引用变量的test方法时,实际上是执行PloymorphismTest001类中覆盖后的test方法,这就是多态。

当把一个子类对象直接赋给父类引用变量,例如上面的SuperClass sscc = new PloymorphismTest001();这个sscc引用变量的编译时类型是SuperClass,而运行时类型是PloymorphismTest001,当运行时调用该引用变量的方法时,其方法行为总是像子类方法的行为,而不是像父类方法行为,这将出现相同类型的变量、执行同一个方法时呈现出不同的行为特征,这就是多态。

特别提醒:

与方法不同的是,对象的属性则不具备多态性,如上面的sscc引用变量,程序中输出它的book属性时,并不是输出PloymorphismTest001类里定义的实例属性,而是输出SuperClass类的实例属性。

注意:

我们通过Object p = new Person()代码定义一个变量p,则这个p只能调用Object类的方法,而不能调用Person类里定义的方法。

时间: 2024-12-22 08:05:06

Java中的继承、封装、多态的理解的相关文章

Java中的继承和多态

1.  什么是继承,继承的特点? 子类继承父类的特征和行为,使得子类具有父类的各种属性和方法.或子类从父类继承方法,使得子类具有父类相同的行为. 特点:在继承关系中,父类更通用.子类更具体.父类具有更一般的特征和行为,而子类除了具有父类的特征和行为,还具有一些自己特殊的特征和行为. 在继承关系中.父类和子类需要满足is-a的关系.子类是父类. 表示父类和子类的术语:父类和子类.超类和子类.基类和派生类,他们表示的是同一个意思. 2.  为什么需要继承?什么时候应该继承? 使用继承可以有效实现代码

Java中的继承、封装、多态

继承 所谓封装,就是将对象的成员变量和成员函数包装和隐藏起来,对外界通过特定的接口来访问. public class User { private String name; public User (String name) { this.name = name; } public String getName () { return this.name; } public void sayName () { System.out.println(this.getName()); } publi

关于java的this、继承、多态的理解

今天主要学习的内容是关于this.继承.多态的理解,并对其作出总结. 1.This 就目前来说,从个人的实验来看,this主要是对于一个类的对象的引用.它出现的位置主要是以它出现的形式决定的. ①.this(参数类型)这是在在构造方法中调用重写的构造方法. ②.作为某个类的对象来调用类中属性或方法.(用在某个类中的成员方法,因为某个类的对象就可以通过.来调用) 2.extends 继承之前已经了解了一些,接下来就是进一步的总结. ①.protected类型的变量是适合子类和父类之间的使用的,即使

JavaScript基础--面向对象三大特性(八):继承封装多态

一.构造函数基本用法:function 类名(参数列表){属性=参数值} 1 function Person(name,age){ 2 this.name = name; 3 this.age = age; 4 } 5 6 //创建Person对象的时候,可以直接给名字和年龄 7 var p1 = new Person('abc',80); 8 window.alert(p1.name); 9 var p2 = new Person('hello',9); 10 window.alert(p2.

菜鸟译文(一)——Java中的继承和组合

阅读英文的能力对于程序员来说,是很重要的.这几年也一直在学习英文,今天心血来潮,就在网上找了一篇简短的博文翻译一下.水平一般,能力有限,还请各位看官多多指点. 译文: 本文将会举例说明Java中继承和组合的概念.首先举一个继承的例子,然后展示一下如何用组合来改善继承的设计.最后概括一下如何在它们之间做出选择. 1. 继承 假设我们有一个Insect类.这个类包含两个方法:一个是move(),一个是attack(). class Insect { private int size; private

java中的继承与oc中的继承的区别

为什么要使用继承? 继承的好处: (1)抽取出了重复的代码,使代码更加灵活 (2)建立了类和类之间的联系 继承的缺点: 耦合性太强 在OC中的继承是: 1.OC中不允许子类和父类拥有相同名称的成员变量名:(java中是可以的) 2.编译器从上往下执行,所以在子类前面至少应该要有父类的声明:如 @interface Worker : Person @end 3.OC中的子类可以拥有和父类相同名称的方法,在子类调用时,优先去自己的内部寻找,如果父类没有定义该方法,则继续在继承链上查找,直到找到为止,

C中的继承和多态

1.引言 继承和多态是面向对象语言最强大的功能.有了继承和多态,我们可以完成代码重用.在C中有许多技巧可以实现多态.本文的目的就是演示一种简单和容易的技术,在C中应用继承和多态.通过创建一个VTable(virtual table)和在基类和派生类对象之间提供正确的访问,我们能在C中实现继承和多态.VTable能通过维护一张函数表指针表来实现.为了提供基类和派生类对象之间的访问,我们可以在基类中维护派生类的引用和在派生类中维护基类的引用. 2.说明 在C中实现继承和多态之前,我们应该知道类(Cl

java中的继承关系

1.定义 java中的继承是单一的,一个子类只能拥有一个父类:java中所有类的父类是java.lang.Object,除了这个类之外,每个类只能有一个父类: 而一个父类可以有多个子类,可以被多个子类继承: Java只支持单继承,也就是说,一个类不能继承多个类. Java只支持单继承(继承基本类和抽象类),但是我们可以用接口来实现(多继承{实现}接口来实现),脚本结构如: public class One extends Parent implements Two,Three,Four{} 2.

Objective-C中的继承和多态

面向对象编程之所以成为主流的编程思想和他的继承和多态是分不开的,只要是面向对象语言都支持继承和多态,当然不同的OOP语言之间都有其特点.OC中和Java类似,不支持多重继承,但OOP语言C++就支持多继承,为什么OC不支持多继承稍后将会提到.  说到继承呢,想到了一本书上是引用<大话西游>里的一句话来描述继承的.“人是人他妈生的,妖是妖他妈生的!”,想必里面的唐三藏也学过OOP编程,也许他们师徒四人去西天取什么算法导论呢,漫谈OOP编程啦,数据结构啦等这类的书去啦.人和妖都属于动物类,但各自有