封装继承
访问修饰符
- public,对外公开
- protected,对子类和同一个包中的类公开
- 默认级别
- private,只有本身可以访问
访问修饰符的细节
- 修饰符可以用来修饰类中的属性,成员方法以及类
- 只有默认的和public才可以修饰类,并且遵循上述访问权限的特点
- 成员方法的访问规则和属性完全一样
封装
封装就是把抽象出来的数据[属性]和对数据操作[方法]封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作[方法]才能对数据进行操作(对电视机的操作就是典型封装)
可以隐藏实现细节:方法(连接数据库)< - -调用(传入参数)
可以对数据进行验证,保证安全合理
封装实现的步骤
- 将属性私有化(不能直接修改属性)
- 提供一个公告的set方法,用于对数学判断并赋值(可以假如数据验证的业务逻辑)
public void set(类型 参数名)
{
属性=参数名
}
- 提供一个公共的get方法,用于获取属性的值
public 数据类型 get()
{
return xx;
}
封装的简单例子
目的:不能随便查看人的年龄,工资等隐私,年龄要合理设置,name的长度在2~6之间
package com.hh.encap;
public class Encapsulation01 {
public static void main(String[] args) {
Person person=new Person();
person.setName("jack8888");
person.setAge(38);
person.setSalary(30000);
System.out.println(person.info());
}
}
class Person{
public String name;
private int age;
private double salary;
//使用快捷键生成,更快
public String getName() {
return name;
}
public void setName(String name) {
if (name.length() >= 2 && name.length() <= 6) {
this.name = name;
}
else {
System.out.println("你的名字长度不符合要求,需要在2~6,默认姓名为第一书记");
this.name="第一书记";
}
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 1 && age <= 120) {
this.age = age;
}
else{
System.out.println("你设置的年龄不对,需要在1-120以内,给一个默认年龄为18");
this.age=18;//给默认年龄
}
}
public double getSalary() {
//可以在这里增加判断或者限定
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
//写一个方法返回
public String info()
{
return "信息为name= "+name+" age= "+age+" 薪水 "+salary;
}
}
封装与构造器的配合使用
package com.hh.encap;
public class Encapsulation01 {
public static void main(String[] args) {
Person person=new Person();
person.setName("jack8888");
person.setAge(38);
person.setSalary(30000);
System.out.println(person.info());
Person smith=new Person("smith",300,1200);
System.out.println("=============\n"+smith.info());
}
}
class Person{
public String name;
private int age;
private double salary;
public Person()
{
}
//三个属性的构造器
public Person(String name, int age, double salary) {
//可以将set方法下载构造器,仍然可以验证
setName(name);
setAge(age);
setSalary(salary);
}
public String getName() {
return name;
}
public void setName(String name) {
if (name.length() >= 2 && name.length() <= 6) {
this.name = name;
}
else {
System.out.println("你的名字长度不符合要求,需要在2~6,默认姓名为第一书记");
this.name="第一书记";
}
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 1 && age <= 120) {
this.age = age;
}
else{
System.out.println("你设置的年龄不对,需要在1-120以内,给一个默认年龄为18");
this.age=18;//给默认年龄
}
}
public double getSalary() {
//可以在这里增加判断或者限定
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
//写一个方法返回
public String info()
{
return "信息为name= "+name+" age= "+age+" 薪水 "+salary;
}
}
简单练习
在AccountTest类中进行测试
package com.hh.encap;
public class AccounTest {
public static void main(String[] args) {
Account cu=new Account("puy",200.1,"457897");
System.out.println(cu.info());
}
}
package com.hh.encap;
public class Account {
private String name;
private double account;
private String cord;
public Account(String name, double account, String cord) {
this.setName(name);
this.setAccount(account);
this.setCord(cord);
}
public String getName() {
return name;
}
public void setName(String name) {
if (name.length() ==2|| name.length() == 4||name.length()==3) {
this.name = name;
} else {
System.out.println("名字的长度需要在2~4之间,默认值为冯书记");
this.name="冯书记";
}
}
public double getAccount() {
return account;
}
public void setAccount(double account) {
if(account>20)
{
this.account = account;
}
else{
System.out.println("余额不满20,系统设置默认值为20");
this.account=20;
}
}
public String getCord() {
return cord;
}
public void setCord(String cord) {
if(cord.length()==6)
{
this.cord = cord;
}
else{
System.out.println("你输入的密码长度不符合6位,系统默认密码位123456");
this.cord="123456";
}
}
public String info()
{
return "您的信息是:"+name+"余额: "+account+"密码:"+cord;
}
}
继承
为什么需要继承?
package com.extend_;
public class Extend01 {
public static void main(String[] args) {
Pupil p=new Pupil();
p.name="小明";
p.age=10;
p.show();
p.setScore(90);
p.info();
System.out.println("=====================");
Graduate g=new Graduate();
g.name="cmg";
g.age=21;
g.show();
g.setScore(100);
g.info();
}
}
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 show()
{
System.out.println("小学生"+name+"正在考试小学数学");
}
public void info()
{
System.out.println("信息如下: 姓名:"+name+"年龄:"+age+"成绩"+score);
}
}
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 show()
{
System.out.println("大学生"+name+"正在考试大学数学");
}
public void info()
{
System.out.println("学生名:"+name+"年龄:"+age+"成绩"+score);
}
//两个类很多是相同
}
从这三个可以看出,代码的冗余度很高,大部分的属性和方法是意愿的,因此需要代码复用
继承的基本语法
class 子类 extends 父类
{
}
- 子类就会自动拥有父类定义的属性和方法
- 父类又叫超类和基类
- 子类又叫派生类
继承的简单使用
创建一个父类将Graduate和pupil共有的属性和方法放在一起
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 info()
{
System.out.println("信息如下: 姓名:"+name+"年龄:"+age+"成绩"+score);
}
}
子类继承
package com.extend_.improve_;
public class Graduate extends Student{
public void show()
{
System.out.println("大学生"+name+"正在考试大学数学");
}
}
package com.extend_.improve_;
//pupil继承student类
public class Pupil extends Student{
public void show()
{
System.out.println("小学生"+name+"正在考试小学数学");
}
}
细节
- 代码复用性提高
- 拓展性和维护性提高了
- 子类继承了所有的属性和方法,但是私有属性和方法不能在子类直接访问,要通过父类提供的公共的方法去访问
- 子类必须调用父类的构造器,完成父类的初始化
- 如果父类没有提供无参构造器,则必须在子类的构造器中使用super去指定使用父类的哪个构造器完成对父类的初始化工作
- 如果希望指定去调用父类的某个构造器,则显式的调用一下:super(参数列表)
- super在使用时,需要放在构造器第一行
- super()和this()都只能放在构造器第一行,因此两个方法不能共存在同一个构造器
- Java所有类是Object类的子类
- 父类构造器的调用不限于直接父类。将一直往上追溯到object类
- 子类最多只能继承一个父类(直接继承),单继承机制
- 不能滥用继承,子类和父类之间必须满足is-a的逻辑关系
继承的本质
当子类对象创建好后,建立查找关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F3nC3cI4-1631068658032)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/3eaa4575-1ba6-4cc3-874c-c5cee17d1d51/Untitled.png)]
package com.extend_;
public class ExtendsTheory {
public static void main(String[] args) {
Son son=new Son();
System.out.println(son.name);
System.out.println(son.age);
}
}
class Grandpa{
String name="大头爷爷";
String hobby="旅游";
}
class Father extends Grandpa{
String name="大头爸爸";
int age=39;
}
class Son extends Father{
String name="大头儿子";
}
package com.extend_;
public class ExtendsTheory {
public static void main(String[] args) {
B b=new B();//调用B类的无参构造器
}
}
class A{
A()
{
System.out.println("a");
}
A(String name)
{
System.out.println("a name");
}
}
class B extends A{
B()
{
this("abc");
System.out.println("b");
}
B(String name)
{
System.out.println("b name");
}
}
输出结果
a
b name
b
-
答案解析
main方法里创建了b,我们看到类B是继承类A,因此创造了无参构造器后,需要跳转到父类,由于是无参输出a,然后A(String name)跳过,执行到this(“abc”),执行B(String name)输出b name,然后this("abc”)结束执行,执行输出b的语句。
package com.newkk;
public class Exercise2 {
public static void main(String[] args) {
C c=new C();
}
}
class A{
public A()
{
System.out.println("我是A类");
}
}
class B extends A{
public B()
{
System.out.println("我是B类的无参构造");
}
public B(String name)
{
System.out.println(name+"我是B类的有参构造");
}
}
class C extends B
{
public C()
{
this("hello");//调用本类的有参构造
System.out.println("我是C类的无参构造");
}
public C(String name)
{
super("hahah");
System.out.println("我是C类的有参构造");
}
}
我是A类
hahah我是B类的有参构造
我是C类的有参构造
我是C类的无参构造
关于电脑的一个简单小例子
package com.Extendexercise3;
public class Test {
public static void main(String[] args) {
PC pc=new PC("intel",16,500,"IBM");
pc.info();
NotePad pad=new NotePad("Intel",16,500,"red");
pad.info2();
}
}
package com.Extendexercise3;
public class Computer {
private String CPU;
private double memory;
private int disk;
public Computer(String CPU, double memory, int disk) {
this.CPU = CPU;
this.memory = memory;
this.disk = disk;
}
public String getCPU() {
return CPU;
}
public void setCPU(String CPU) {
this.CPU = CPU;
}
public double getMemory() {
return memory;
}
public void setMemory(double memory) {
this.memory = memory;
}
public int getDisk() {
return disk;
}
public void setDisk(int disk) {
this.disk = disk;
}
public String getDetail()
{
return "电脑的信息为:"+"CPU: "+CPU+"内存容量: "+memory+"硬盘:"+disk;
}
}
package com.Extendexercise3;
public class PC extends Computer{
private String brand;
//IDEA根据继承的原则,自动把构造器的调用写好
public PC(String CPU, double memory, int disk, String brand) {
super(CPU, memory, disk);
this.brand = brand;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public void info()
{
System.out.println(getDetail()+"品牌是"+brand);
}
}
package com.Extendexercise3;
public class NotePad extends Computer{
private String color;
public NotePad(String CPU, double memory, int disk, String color) {
super(CPU, memory, disk);
this.color = color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public void info2()
{
System.out.println(getDetail()+"颜色"+color);
}
}
super关键字
- super代表父类的引用,用于访问父类的属性、方法、构造器
- super能访问父类的属性和方法,但不能是private
super().方法名
super().属性
super(参数列表)用于访问构造器
super的使用细节
- 调用父类的构造器好处:分工明确,父类属性由父类初始化
- 当子类有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super
- 访问n1和this.n1
- 多个父类有同名的成员,使用super访问遵循就近原则
方法的重写
子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法
子类方法不能缩小类方法的访问权限
重写的案例
package com.person;
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String say()
{
return "我是:"+name+"年龄:"+age;
}
}
package com.person;
public class Student extends Person{
private int id;
private double score;
public Student(String name, int age) {
super(name, age);
}
public Student(String name, int age, int id,double score) {
super(name, age);
this.id = id;
this.score = score;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public String say()//super的好处
{
return super.say()+"id:"+id+"score"+score;//调用父类的C方法
}
}
package com.person;
public class test {
public static void main(String[] args) {
Person man=new Person("王东",50);
System.out.println(man.say());
Student smith=new Student("smith",90,855,98.1);
System.out.println(smith.say());
}
}