面相对象中级(包、访问修饰符、封装、继承、super关键字)

面相对象中级(包、访问修饰符、封装、继承、super关键字)2 当子类中有和父类中的成员 属性和方法 重名时 为了访问父亲的成员 必须通过 super

一、包

1.1包的基础概念

1.2包的本质

包的本质实际上就是创建不同的文件夹来保存类文件,示意图如下:

  

                      

包就是两个文件夹,同一个包下方法的名称不能相同,但不同包下方法的名称可以相同。虽然名称相同,但这可以是两个完全不相同的类。

1.3包的基本代码

引入包

package com.use; import com.baostudy.Dog; public class test { public static void main(String[] args) { Dog dog = new Dog(); com.modifierStudy.Dog dog1 = new com.modifierStudy.Dog(); /* 为了区分两个dog,下面的用包名进行区分 本质用途还是一样的。 */ } }

一些常见的包

1.4包的相关细节

二、访问修饰符

2.1访问修饰符的基本概念

2.2访问修饰符的相关细节

三、封装

3.1封装的基础概念

封装就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序其它部分只有通过被授权的操做[方法],才能对数据进行操作。(电视机就是一个例子,开关电视机在电视机内部是一个非常复杂的过程,但对于用户来说只需要按一下开关键。用户无法改变内部结构。)

3.2封装的实现

3.3封装的实例代码

要求如下:

package com.ssj.encap; public class Encapsulation01 { public static void main(String[] args) { Person person = new Person(); person.setName("jack"); person.setSalary(30000); person.setAge(30); System.out.println(person.name); //工资和年龄只有通过get才能查到,不能直接查到 //可以在get上增加一些逻辑比如:密码。才能查询 person.getSalary("admin"); person.getAge("aaaaa"); } } class Person{ public String name; private int age; private double salary; //自己写setxxx和getxxx太慢了,使用快捷键。 //alt+insert选择(Getter and Setter) //然后根据要求完善代码 public String getName() { return name; } public void setName(String name) { this.name = name; } public void getAge(String lock) { if(lock == "admin") { System.out.println(age); } else{ System.out.println("密码错误,没有权限访问年龄"); } } public void setAge(int age) { if (age >= 1 && age <= 120) { this.age= age; } else{ System.out.println("你设置的年龄不对,年龄需要在 1-120 ,给你默认年龄18"); this.age = 18; } } public void getSalary(String lock) { if(lock == "admin") { System.out.println(salary); }else{ System.out.println("密码错误,没有权限访问工资"); } } public void setSalary(double salary) { this.salary = salary; } } 

由上可知封装的好处:1.可以隐藏实现细节2.可以对数据进行验证(set方法),保证安全合理(在get中增加逻辑)。

上述代码有个问题,因为在实际应用的过程中会顺手写构造器,以便随时能用。(就不用一个参数一个set方法了)如果使用构造器进行赋值的话就可以绕过set方法,这样就不能验证了。解决代码如下:

 public Person(String name, int age, double salary) { this.name = name; this.age = age; this.salary = salary; setSalary(salary); setName(name); setAge(age); }

在构造器中调用set方法就可以避免这个问题了。

package com.ssj.encap; public class Encapsulation01 { public static void main(String[] args) { Person person = new Person("jack",30,30000); System.out.println(person.name); person.getSalary("admin"); person.getAge("aaaaa"); //工资和年龄只有通过get才能查到,不能直接查到 //可以在get上增加一些逻辑比如:密码。才能查询 } } class Person{ public String name; private int age; private double salary; //自己写setxxx和getxxx太慢了alt+insert //选择(Getter and Setter) //然后根据要求完善代码 public Person(String name, int age, double salary) { this.name = name; this.age = age; this.salary = salary; setSalary(salary); setName(name); setAge(age); } public String getName() { return name; } public void setName(String name) { this.name = name; } public void getAge(String lock) { if(lock == "admin") { System.out.println(age); } else{ System.out.println("密码错误,没有权限访问年龄"); } } public void setAge(int age) { if (age >= 1 && age <= 120) { this.age= age; } else{ System.out.println("你设置的年龄不对,年龄需要在 1-120 ,给你默认年龄18"); this.age = 18; } } public void getSalary(String lock) { if(lock == "admin") { System.out.println(salary); }else{ System.out.println("密码错误,没有权限访问工资"); } } public void setSalary(double salary) { this.salary = salary; } } 

四、继承

4.1继承的基础概念

先看两段代码;

package com.extend; //大学生考试 public class Graduate { public String name; public int age; private double score; public void setScore(double score) { this.score = score; } public void testing(){ System.out.println(" 大学生 " + name + " 正在考大学数学 "); } public void showInfo(){ System.out.println(" 学生名 " + name + " 年龄 " + age + " 成绩 " + score); } } 
package com.extend; //小学生考试 public class pupil { public String name; public int age; private double score; public void setScore(double score) { this.score = score; } public void testing(){ System.out.println(" 小学生 " + name + " 正在考小学数学 "); } public void showInfo(){ System.out.println(" 学生名 " + name + " 年龄 " + age + " 成绩 " + score); } } 

通过看上述两段代码不难发现,代码中有很多重复的部分也有不重复的部分,对于重复部分其实是学生的共有属性,重复写很麻烦,可以采取继承的方式解决这一问题。

4.2继承的基本代码

对于开头的代码运用继承进行优化。

父类:

package com.extend.improve_; //父类:是pupil和graduate的父类 public class student { //共有属性 public String name; public int age; private double score; //共有方法 public void setScore(double score) { this.score = score; } public void showInfo(){ System.out.println(" 学生名 " + name + " 年龄 " + age + " 成绩 " + score); } }

子类: 

package com.extend.improve_; public class pupile extends student{ public void testing(){ System.out.println(" 小学生 " + name + " 正在考小学数学 "); } } 
package com.extend.improve_; public class Graduate extends student{ public void testing(){ System.out.println(" 大学生 " + name + " 正在考大学数学 "); } } 

主函数 

package com.extend.improve_; public class Extends01 { public static void main(String[] args) { pupile pupile = new pupile(); pupile.name = "银角大王"; pupile.age = 10; pupile.testing(); pupile.setScore(60); pupile.showInfo(); System.out.println("========"); Graduate graduate = new Graduate(); graduate.name = "金角大王"; graduate.age = 22; graduate.testing(); graduate.setScore(100); graduate.showInfo(); } } 

4.3继承的本质

4.4继承的相关细节 

(1)子类继承了所有的属性和方法,但是私有(private)属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问。

private int name = 10; public void getName{ System.out.println(name) } private void test400(){ System.out.println("test400"); } public void getTest400(){ test400(); }

(2)子类必须调用父类的构造器,完成父类的初始化。

(3)当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中使用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。[对于上面这段话可以一句一句去理解]

当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器

package com.extend.improve_; public class Sub extends Base { public Sub(){ //super()默认调用父类的无参构造器 System.out.println("子类sub()构造器被调用"); } //当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器 public Sub(String name){ System.out.println("子类Sub()构造器被调用"); } public void sayOk(){ //非私有的属性和方法可以在子类直接访问 //但是私有属性和方法不能在子类直接访问 System.out.println(n1+" "+n2+" "+n3); test100(); test200(); test300(); } } 
package com.extend.improve_; public class Base { public int n1 = 100; protected int n2 = 200; int n3 = 300; private int n4 = 400; public Base(){ System.out.println("父类Base()构造器被调用"); } public int gtN4(){ return n4; } public void test100(){ System.out.println("test100"); } protected void test200(){ System.out.println("test200"); } void test300(){ System.out.println("test300"); } private void test400(){ System.out.println("test400"); } public void getTest400(){ test400(); } } 
package com.extend.improve_; public class extemdsDetail { public static void main(String[] args) { Sub sub = new Sub();//创建一个子类对象 System.out.println("===第二个对象==="); Sub sub1 = new Sub("jack"); } } 

                         

通过上述代码及其运行结果可以看出,只调用了子类的构造器,父类的构造器也被调用了。

如果父类没有提供无参构造器,则必须在子类的构造器中使用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。

 因为子类中的super()默认(super是隐含存在的,只是编译器自带的)调用父类的无参构造器,而父类没有加无参构造器,因此代码报错。解决办法:

package com.extend.improve_; public class Sub extends Base { public Sub(){ super("smith",10); System.out.println("子类sub()构造器被调用"); } //当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器 public Sub(String name){ super("tom",30);//因为父类中没有无参构造器 //需要super去指定调用父类的哪一个构造器 System.out.println("子类Sub()构造器被调用"); } public void sayOk(){ //非私有的属性和方法可以在子类直接访问 //但是私有属性和方法不能在子类直接访问 System.out.println(n1+" "+n2+" "+n3); test100(); test200(); test300(); } } 

(4)如果希望指定去调用父类的某个构造器,则显式的调用一下:super()

(5)super在使用时,需要放在构造器的第一行(因为是先调用父类的构造在再调用子类的构造器)

(6)super和this都只能放在构造器的第一行。因次这两个方法不能同时存在在同一个构造器内 

(7)java所有类都是object类的子类(通过快捷键ctrl+H(IEDA))

(8)父类构造器的调用不限于直接父类,将一直往上追溯直到Object(顶级父类)

(9)子类最多只能继承一个父类,即java中是单继承机制,即(A->B,A->C(->代表继承))是不可实现的。

(10)不能滥用继承,子类和父类必须满足is -a的逻辑关系

五、super关键字

5.1super关键字的基础概念

super代表父类的引用,用于访问父类的属性、方法、构造器。

(1)访问父亲的属性,但不能访问父亲的private属性

(2)访问父亲的方法,但不能访问父亲的private方法

(3)访问父亲的构造器

5.2super关键字的基础代码

父类:

package com.super_; public class A { public int n1 = 100; protected int n2 = 200; int n3 = 300; private int n4 = 400; public A(){} public A(String name){} public A(String name,int age){} public void test100(){ } public void test200(){ } void test300(){ } private void test400(){ } } 

子类:

package com.super_; public class B extends A{ //访问父类的属性,但不能访问父类的private属性 public void hi(){ System.out.println(super.n1+" "+super.n2+" "+super.n3); } //访问父类的方法,但不能访问父类的private方法 public void ok(){ super.test100(); super.test200(); super.test300(); //super.test400();不能访问父类私有的方法 } //访问父类的构造器:super(参数列表);只能放在构造器的第一句,只能出现一句! public B(){ super(); //super("jack"); //super("jack",10); } } 

5.3super关键字的相关细节

1.调用父类构造器的好处(分工明确,父类属性由父类初始化,子类的属性由子类初始化)

2.当子类中有和父类中的成员(属性和方法)重名时,为了访问父亲的成员,必须通过super。如果没有重名,使用super、this、直接访问时一样的效果。

3.super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;如果多个基类(上级类)中有同名成员,使用super访问遵循就近原则。

今天的文章 面相对象中级(包、访问修饰符、封装、继承、super关键字)分享到此就结束了,感谢您的阅读。
编程小号
上一篇 2024-12-16 20:30
下一篇 2024-12-16 20:27

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/87786.html