`

day_09_Java类的封装、继承与多态

阅读更多

星期二, 十一月 10, 2015 10:34:07

 

 

封装

 

继承

  可以从一个简单的类继承出相对复杂高级的类

 

多态

      可以动态的对对象进行调用,使对象之间变得相对独立。

 

 

一:类的封装性

 

1.看下面的案例、

 

 ----1.1代码案例:

package day09;

 

public class CapsulationTest {

public static void main(String[] args) {

Person p = new Person();

p.age = -23;

p.name = "宇宙歆儿";

p.talk();

}

}

 

class Person {

String name;

int age;

Person() {

}

 

public void talk() {

System.out.print("我的名字叫:"+name+"\n"+"年龄:"+age);

}

}

 

运行结果:

我的名字叫:宇宙歆儿

年龄:-23

 

 

注意:

加工的原料有问题,生产出来的也有问题。

而导致这种错误的原因是,就是因为程序在原料的入口没有校验。

 

 

----1.2.类的封装实例

 

        之前所列举的程序都是用对象直接访问类中的属性,这在面向对象法则中是不允许的。

所以为了避免程序中这种错误的发生,在一般的的开发中往往要将类中的属性封装(private)。

 

代码案例:

package day09;

 

public class CapsulationTest {

public static void main(String[] args) {

Person p = new Person();

p.age = -23;

p.name = "宇宙歆儿";

p.talk();

}

}

 

class Person {

private String name;//设置为private

private int age;//设置为private

Person() {

}

 

public void talk() {

System.out.print("我的名字叫:"+name+"\n"+"年龄:"+age);

}

}

 

结果:

p.age = -23;

p.name = "宇宙歆儿";

 

直接对对象的属性进行访问,出现报错。是因为设置的属性为private,不可以直接对其进行访问。

 

注意:

     为私有的,不可以直接访问,这样就可以保证对象无法直接去访问类中的属性。

 

但是如果非要给对象赋值的话,解决方法是:

    会增加一些方法,如 setXxx()、 getXxx()这样的公用方法来解决这一矛盾。

 

----1.3自己总结:

 

1.通过set方法进行将privat的值改变

  改变完了还是private的修饰符

 

2.要使用get方法取出私有属性的值

  然后转换为外部可访问的值。

 

 

----1.4代码案例:

package day09;

 

public class CapsulationTest {

public static void main(String[] args) {

Person p = new Person();

p.setName("宇宙歆儿");

p.setAge(3);

/*p.getAge();

p.getName();*/

p.talk();//这个不用调用get是因为talk()已经可以访问了

}

}

 

/*setXxx()、 getXxx()为了解决:

    但是如果非要给对象赋值的话,解决方法是:

    会增加一些方法,如 setXxx()、 getXxx()这样的公用方法来解决这一矛盾。*/

class Person {

private String name;

private int age;

Person() {

}

 

public void talk() {

System.out.print("我的名字叫:"+name+"\n"+"年龄:"+age);

}

 

public void setName(String name) {

   this.name = name;

}

 

public void setAge(int a) {

if (a > 0) {

this.age = a;

}

}

 

public String getName() {

return name;

}

 

public int getAge () {

return age;

}

}

运行结果:

我的名字叫:宇宙歆儿

年龄:3

 

在set中设置了判断合理性

,设置age = -23

 

运行结果:

我的名字叫:宇宙歆儿

年龄:0

age为默认值0,可以保证数据的安全性。

 

 

注意:

 

    关于封装与否并没有明确的规定,不过从程序设计的角度来说,一般来说设计较好的程序的类中的属性都是需要封装的。

 

此时则只能使用setXxx()、getXxx()方法,这是一个明确的标准的规定。

 

 

将属性进行私有化

 

----1.5封装的优点:

 

   (1)隐藏类的实现细节;

   (2)让使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作;

   (3)便于修改,增强代码的可维护性;

 

 

 

二.类的继承

 

  类的继承可以以既有类为基础,进而派生出新的类。

通过这种方式,便能快速地开发出新的类,

而不是编写相同的程序代码,这就是程序代码再利用的概念。

 

----2.1继承的基本概念

 

 

在Java中,通过继承可以简化类的定义,扩展类的功能。

在Java中支持类单继承和多继承,但是不支持多继承,

即一个类只能继承一个类而不能继承多个类。

 

继承的格式:

    class 子类名 extends 父类

 

 

 

Java继承

-----只能直接继承父类中的公有属性和公有方法,

而隐含地(不可见地)继承了私有属性。

 

----2.2类的继承的实例

 

代码案例:

package day09;

 

public class InheritTest {

public static void main(String[] args) {

Student s1 = new Student();

   s1.setName("瓦询");

   s1.setAge(24);

   s1.setSchool("丰趣海淘");

   System.out.println(s1.getName()+"\n"+s1.getAge()+"\n"+s1.getSchool());

}

}

 

class Person{

private String name ;

private int    age;

public void setName(String name) {

this.name = name;

}

public String getName() {

return name;

}

public void setAge(int age) {

this.age = age;

}

public int getAge() {

return age;

}

}

 

class Student extends Person {

private String school;

 

public void setSchool(String school) {

this.school = school;

}

 

public String getSchool() {

return school;

}

}

 

 

运行结果:

瓦询

24

丰趣海淘

 

注意:

    在Java中只允许单继承,而不允许多重继承,也就是说一个子类只能有一个父类。

但是Java中却允许多层继承。A<--B<--C

 

 

 

----2.3.类的继承专题研究

 

关于继承的问题,有一些概念和过程需要澄清,有些语法和术语需要熟练掌握。本节做一些总结。

 

2.3.1子类对象的实例化过程

 

结论:

    子类对象在实例化时会默认先去调用父类中的无参构造方法,之后再调用本类中的相应的构造方法。

 

代码案例:

package day09;

 

public class InheritTest {

public static void main(String[] args) {

Student s1 = new Student();

}

}

 

class Person{

String name ;

int    age;

public Person() {

System.out.print("public Person()"+"\n");

}

}

 

class Student extends Person {

String school;

public Student() {

/*super();*/

System.out.print("public Student()");

}

}

 

运行结果:

public Person()

public Student()

 

2.3.2 super关键字

 

结论:

    super主要的功能时完成子类调用父类中的内容,也就是调用

父类中的属性或方法。

 

 

注意:

   用super调用父类中的构造方法,只能放在程序的第1行。

 

代码案例:

/*用super调用父类中的构造方法*/

package day09;

 

public class InheritTest {

public static void main(String[] args) {

Student s1 = new Student();

s1.school = "海淘";

System.out.print("姓名:"+s1.name+"\n年龄: "+s1.age+"\n学校:"+s1.school);

}

}

 

class Person{

String name ;

int    age;

public Person(String n,int a) {

this.name = n ; 

this.age = a;

}

}

 

class Student extends Person {

String school;

public Student() {

super("宇宙歆儿7",25);

}

}

 

运行结果:

姓名:宇宙歆儿7

年龄: 25

学校:海淘

 

super关键字不仅可用于调用父类中的构造方法,也可用于调用父类中的属性和方法。

 

格式:

   super.父类中的属性;

   super.父类中的方法()

 

2.3.3通过super调用父类的属性和方法

 

代码案例:

 

package day09;

 

public class InheritTest {

public static void main(String[] args) {

Student s1 = new Student("刘惜君",28,"恋风恋歌");

System.out.print(s1.school);

}

}

 

class Person{

String name ;

int    age;

public Person() {

}

 

public String talk() {

return "...名称:"+name+"\n年龄:"+age;

}

 

}

/*通过super调用父类的属性和方法*/

class Student extends Person {

 

String school;

public Student(String name,int age,String school) {

super.name = name;//在这里使用super进行调用父类的属性

super.age = age;

System.out.println(super.talk());//调用父类中的方法

this.school = school;//调用本类中的属性

}    

}

 

运行结果:

...名称:刘惜君

年龄:28

恋风恋歌

 

本例中,super换成this也是可以的,那为什么还要用super呢?

----见下例

 

2.3.4.限制子类的访问

 

  有些时候,父类并不希望子类可以访问自己的类中全部的属性和方法,所以需要将一些属性与方法隐藏起来,不让子类去使用。

为此可在声明属性或方法时加上“private”关键字,表示私有。

 

代码案例:

 

package day09;

 

public class InheritTest {

public static void main(String[] args) {

Student s = new Student();

s.setVar();

System.out.println("名称:"+s.getName()+"\n"+s.getAge());

}

}

 

class Person{

private String name ;

private int    age;

 

public void setName(String name) {

this.name = name;

}

public String getName() {

return name;

}

public void setAge(int age) {

this.age = age;

}

public int getAge() {

return age;

}

}

 

class Student extends Person {

public void setVar() {

super.setName("宇宙");

super.setAge(1111);

}

}

 

运行结果:

名称:宇宙

年龄:1111

 

2.3.5最后注意 super 与 this 的区别

 

        super 不是一个对象的引用,

       不能将 super 赋值给另一个对象变量,

      它只是一个指示编译器调用父类方法的特殊关键字。

 

super 关键字的功能:

调用父类中声明为 private 的变量。

点取已经覆盖了的方法。

作为方法名表示父类构造方法。

 

2.3.6代码案例:

package day09;

 

public class InheritTest {

public static void main(String[] args) {

Student s = new Student();

s.setVar();

}

}

 

class Person{

private String name = "jami soul she";

 

public String getName() {

return name;

}

}

 

class Student extends Person {

public void setVar() {

// 通过 getter 方法调用父类隐藏变量

     System.out.println(super.getName());

}

}

 

运行结果:

jami soul she

 

 

----4.覆盖

 

在程序中可以看到,在子类中可以通过super.方法()调用父类中被子类覆盖的方法。

 

代码案例:

/*验证在遇到方法的覆盖时,可以使用super调用父类的方法 */

package day09;

 

public class InheritTest {

public static void main(String[] args) {

Student s = new Student("五月天",32,"五迷五迷");

System.out.print(s.talk1());

}

}

 

class Person{

String name ;

int age;

public String talk1() {

return "姓名="+name+"\n年龄="+age;

}

}

 

class Student extends Person {

String school;

 

public Student(String name,int age,String sc){

this.name = name;

this.age = age;

this.school = sc;

}

public String talk1() {

/*不加这个的话,父类的talk1()方法不会被执行,因子类已经进行了方法的覆盖*/

return super.talk1()+"\n公司="+school;

}

}

 

运行结果:

姓名=五月天

年龄=32

公司=五迷五迷

 

 

三.类的多态

 

最重要的一个特性---多态

 

----3.1 多态的基本概念

 

重载的最终效果是调用同一个方法名称,却可以根据传入的参数不同的处理结果,这其实就是多态的一种体现。

 

 

代码案例:

package day09;

 

public class PolymorphismTest {

public static void main(String[] args) {

 

/*父类的对象通过子类进行的实例化,

* 所以在调用fun1(时,

* 调用的是子类的次方法*/

Person p = new Student();

p.fun1();

p.fun2();

}

}

 

class Person {

public void fun1() {

System.out.println("1.fun1()");

}

public void fun2() {

System.out.println("2.fun2()");

}

}

 

class Student extends Person{

//进行覆盖父类的fun1()方法

public void fun1() {

System.out.println("3.fun1()");

}

public void fun4() {

System.out.println("4.fun4()");

}

}

运行结果:

3.fun1()

2.fun2()

 

 

      案例的原因是因为父类对象并非由其本身的类实例化,而是通过子类实例化

这就是所谓的对象的多态性,即子类实例化对象可以转换为父类实例化对象

 

星期二, 十一月 10, 2015 19:22:18   Java从入门到精通P182

 

----3.2 类的多态实例

 

在这里要讲解两个概念,予以重视。

 

3.2.1向上转型

 

向上转型

在上个例子中,父类对象通过子类对象去实例化,实际上就是对对象的向上转型。

向上转型是不需要进行强制类型转换的,但是向上转型会丢失精度。

 

向下转型

就是父类的对象可以转换为子类对象,但是需要注意的是,

这时则必须要进行强制的类型转换。

 

总结:

 

1.向上转型可以自动完成

2.向下转型必须进行强制类型转换

 

注意:

 

 

并非全部的父类对象都可以强制转换为子类对象。

代码案例:

package day09;

 

public class PolymorphismTest {

public static void main(String[] args) {

 

/*父类的对象通过子类进行的实例化,

* 所以在调用fun1(时,

* 调用的是子类的次方法*/

 

/*Person p = new Person();

将p向下转型:

* 父类用其本身类实例化自己的对象,

* 但它并不知道谁是自己的子类,

* 那肯定在转换时会出现错误。

* Exception in thread "main" java.lang.ClassCastException:

*  day09.Person cannot be cast to day09.Student

at day09.PolymorphismTest.main(PolymorphismTest.java:11)

Student p2 = (Student)p;

*/

 

Person p = new Student();//p为person的子

Student p2 = (Student)p;

p2.fun1();

p2.fun2();

 

 

 

}

}

 

class Person {

public void fun1() {

System.out.println("1.fun1()");

}

public void fun2() {

System.out.println("2.fun2()");

}

}

 

class Student extends Person{

//进行覆盖父类的fun1()方法

public void fun1() {

System.out.println("3.fun1()");

}

public void fun3() {

System.out.println("4.fun3()");

}

}

 

运行结果:

3.fun1()

2.fun2()

 

问题总结:

 

   父类用其本身类实例化自己的对象,但它并不知道谁是自己的子类,那肯定在转换时

会出现错误。

 

修改方法:

  将实例化代码改为Person p = new Studengt();

这样就是由子类去实例化父类对象,

也就是说这个时候父类知道有这么一个子类,也就是相当于父亲知道自己有这么一个孩子。

所以下面再进行转换时就不会再有问题。

 

星期二, 十一月 10, 2015 20:08:41

 

 

 

1
0
分享到:
评论

相关推荐

    Java入门基础学习资料day09-10

    day06【类与对象、封装、构造方法】 day07【Scanner类、Random类、ArrayList类】 day08【String类、static关键字、Arrays类、Math类】 day09【继承、super、this、抽象类】 day10【接口、多态】 day11【final、权限...

    Java入门基础学习资料day11

    day06【类与对象、封装、构造方法】 day07【Scanner类、Random类、ArrayList类】 day08【String类、static关键字、Arrays类、Math类】 day09【继承、super、this、抽象类】 day10【接口、多态】 day11【final、权限...

    Java入门基础学习资料day07-08

    day06【类与对象、封装、构造方法】 day07【Scanner类、Random类、ArrayList类】 day08【String类、static关键字、Arrays类、Math类】 day09【继承、super、this、抽象类】 day10【接口、多态】 day11【final、权限...

    Java入门基础学习资料day01-02

    day06【类与对象、封装、构造方法】 day07【Scanner类、Random类、ArrayList类】 day08【String类、static关键字、Arrays类、Math类】 day09【继承、super、this、抽象类】 day10【接口、多态】 day11【final、权限...

    Java入门基础学习资料day05-06

    day06【类与对象、封装、构造方法】 day07【Scanner类、Random类、ArrayList类】 day08【String类、static关键字、Arrays类、Math类】 day09【继承、super、this、抽象类】 day10【接口、多态】 day11【final、权限...

    Java入门基础学习资料day03-04

    day06【类与对象、封装、构造方法】 day07【Scanner类、Random类、ArrayList类】 day08【String类、static关键字、Arrays类、Math类】 day09【继承、super、this、抽象类】 day10【接口、多态】 day11【final、权限...

    java7hashmap源码-java:Java

    day07_高级类特性1:封装、继承特性、方法重写与方法重载区别、this关键字 day08_高级类特性1:多态特性、4中访问权限修饰符、this与super区别、==与equals方法区别、instanceof操作符 day09_高级类特性1:toString...

    day8.rar_Java编程_Java_

    定义一个 person类 要求有:属性 方法 封装 多态 继承

    python面向对象day04.txt

    封装(类和私有变量) 继承 多态(python只能实现动态) issubclass(cls, 类或元组) 多继承 一个子类继承自两个或两个以上的父类 类的 __mro__ 属性绑定类的元组 用来记录方法的查找顺序 super 函数是按mro ...

    java经典面试2010集锦100题(不看你后悔)

    A) 抽象类使类与类之间依旧具有父子联系,而接口一般只是定义了一种规范,并不使实现的接口之间具有父子关系。 B) 可以为抽象类定义对象,但是不能为接口定义对象。 C) 抽象类与接口的用法几乎都相同,具体用哪一个...

    30天搞定Java–day9

    面向对象的三大特征:封装、继承、多态 其它关键字:this、super、abstract、interface、static、final、package、import 谈谈你对面向对象中类和对象的理解,并指出二者的关系? 类:抽象的、概念上的内容 对象:...

    day01.环境变量,HelloWorld,常量

    - **第二部分:Java面向对象核心逻辑:**`类和对象`、`封装`、`继承`、`多态`、`抽象`、`接口` - **第三部分:JavaSE核心高级应用:**`集合`、`I/O`、`多线程`、`网络编程`、`反射机制`、 - **第四部分:Java新特性...

    整理后java开发全套达内学习笔记(含练习)

    Encapsulation[java] 封装 (hiding implementation details) Exception [java] 例外; 异常 [ik'sepʃәn] entry n.登录项, 输入项, 条目['entri] enum (关键字) execute vt.执行 ['eksikju:t] exhibit v.显示, ...

Global site tag (gtag.js) - Google Analytics