三大特性-封装,继承和多态
一.封装
1.封装:
将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。
(尽可能隐藏对象的内部实现细节,控制对象的修改及访问的权限。)
get/set方法是外界获取和访问对象私有属性的唯一通道,
2. 注意!!!
- 不管是this还是super都必须是第一行,所以在构造方法中,只能调用其中之一
- super可以调用父类的有参或无惨构造方法 super(); super(" "," ");
- 没有显式的写super(),就会默认调用父类的无参构造方法==>super()
- 写构造方法时,最好写上无参构造方法。避免报错
3.代码演示:
案例一:
public class Test{
public static void main(String[] args) {
Student s1 = new Student();
s1.name = "tom";
//s1.age = 20; //安全,无法直接访问到私有属性
s1.setAge(20); //调用方法完成赋值操作
s1.sex = "male";
s1.score = 99.0;
System.out.println( s1.getAge() ); //调用方法完成取值操作
}
}
class Student{
String name; //属性也称为字段
private int age; //私有属性,本类可见,其他位置不可见
String sex;
double score;
public Student() {}
/**
* 为age属性赋值的方法
*/
public void setAge(int age) { //20000
if(age >= 0 && age <= 153) { //合法区间
this.age = age;
}else {
this.age = 18;//如果录入的数据不合法,默认使用18代表用户的年龄
}
}
/**
* 为age属性取值的方法
*/
public int getAge() {
return this.age;
}
}
案例二:
public class Test{
public static void main(String[] args) {
Teacher t1 = new Teacher();
t1.setName("jack");
t1.setAge(20);
t1.setSex("male");
t1.setSalary(2000.0);
System.out.println(t1.getName() +"\t"+ t1.getAge() +"\t"+ t1.getSex() +"\t"+ t1.getSalary());
}
}
class Teacher{
private String name;
private int age;
private String sex;
private double salary;
public Teacher() {}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return this.age;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getSex() {
return this.sex;
}
public void setSalary(double salary) {
this.salary = salary;
}
public double getSalary() {
return this.salary;
}
}
二.继承
1.继承
- 类与类之间特征和行为的赠与或获得。
- 两个类之间的继承关系,必须满足"is a" 的关系。
2.语法:
class 子类extends父类{}
3.应用:
有继承关系后,子类可以使用父类的属性和方法,也可以定义自己独有的属性和方法
4.好处:
既可以提高代码的复用性,又可以调高代码的可扩张性。
java为单继承,一个类只有一个父类,但可以多级继承
5.访问修饰符
private→default→protected→public 从严到宽
private String a = "A"; //私有的 只有本类可用
String b = "B"; //默认的 default 同包可用
protected String c = "C"; //受保护的
public String d = "D"; //公开的
案例:
public class Animal {
private String name; //私有
int age; //默认访问修饰符
protected String type; //受保护的
public String sex; //公开的
public void test() {
//都可以进行访问
System.out.println(this.name);
System.out.println(this.age);
System.out.println(this.type);
System.out.println(this.sex);
}
}
public class Dog extends Animal {
public void sayHi() {
//System.out.println(name);//私有属性不可访问
//同包默认访问修饰符可用
//不同包子类无法访问
System.out.println(age);
//同包子类可用
//不同包子类可用
System.out.println(type);
System.out.println(sex);
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.test();
Dog g=new Dog();
g.sayHi();
}
}
6.重写与重载的区别
6.1方法重写(在继承的基础上)
原则:
- 方法名相同,参数列表与父类相同
- 返回值类型必须与父类或其子类相同
- 访问修饰符可与父类相同或者比父类更宽
6.2方法重载:
- 方法名相同
- 参数列表不同(个数,位置,类型)
- 与返回值类型和访问修饰符无关
7.super关键字
7.1访问方法
super关键字可在子类中访问父类的方法。
super调方法: super.方法,表示调父类的方法
案例:
public class A { //A类(父类)
public A() {
System.out.println("this is A");
}
}
public class B extends A{ //B类继承A类
public B() {
System.out.println("this is B");
}
}
public class C extends B { //C类继承B类
public C() {
super(); //super会最先调用父类的构造方法
System.out.println("this is C");
}
}
public class Test {
public static void main(String[] args) {
new C();
}
}
7.2访问属性
super调属性: super.属性,表示调父类的属性
7.3调用父类的构造器
- super():表示调用父类无参构造方法。
- super(实参):表示调用父类有参构造方法。
案例:
public class Person {
String name="person";
public void sayHi() {
System.out.println("我们已经sayHi了100遍");
}
}
public class Student extends Person {
String name="student";
public void test() {
String name = "test";
System.out.println(super.name);
System.out.println(this.name);
System.out.println(name);
super.sayHi();
}
public void sayHi() {
//调用父类的方法
super.sayHi();
System.out.println("我来sayhi");
}
}
public class Test {
public static void main(String[] args) {
Student s = new Student();
s.test();
s.sayHi();
}
}
7.4super与this
- this或super使用在构造方法中时,都要求在首行。
- 当子类构造中使用了this()或this(实参),即不可再同时书写super()或super(实参),会由this()指向z构造方法完成super()调用。
案例:
public class Person {
String name="person";
public Person() {
System.out.println("这个是 Person的无参构造方法");
}
public Person(String name ) {
System.out.println("这个是 Person的有参构造方法,参数:"+this.name);
}
public Person(String name,int a ) {
System.out.println("这个是 Person的有参构造方法,参数:"+this.name);
}
}
public class Student extends Person {
String name = "student";
public Student(String name) {
/*
* 不管是this还是super都必须是第一行,所以在构造方法中,只能调用其中之一
*/
// this();
// super("xxx",1); //调用父类的有参构造方法
// super(); //调用父类的无参构造方法
// System.out.println(super);
// System.out.println(this);
System.out.println("这个是student的有参构造方法");
this.name = name;
}
public Student() {
this("名字");
//没有显式的写super(),就会默认调用父类的无参构造方法==>super()
System.out.println("这个是student的无参构造方法");
}
}
public class Test {
public static void main(String[] args) {
new Student();
}
}
三.多态
3.1多态
概念:父类引用指向子类对象,从而产生多种形态。
二者具有直接或间接的继承关系时,父类引用可指向子类对象,即形成多态。
父类引用仅可调用父类所声明的属性和方法,不可调用子类独有的属性和方法。
3.2多态的应用
- 场景一:使用父类作为方法形参实现多态,使方法参数的类型更为宽泛。
- 场景二:使用父类作为方法返回值实现多态,使方法可以返回不同子类对象。
案例:
public class Animal { //动物类(父类)
public void eat() {
System.out.println("吃吃吃");
}
}
public class Cat extends Animal{ //猫类继承动物类
public void eat() {
System.out.println("吃老鼠");
}
public void cry() {
System.out.println("喵哦");
}
}
public class Dog extends Animal{ //狗类继承动物类
public void eat() {
System.out.println("吃肉肉");
}
}
public class Fish extends Animal{ //鱼类继承动物类
public void eat() {
System.out.println("吃小虾米");
}
public void swim() {
System.out.println("我要游泳");
}
}
public class Snake extends Animal{ //蛇类继承动物类
@Override
public void eat() {
System.out.println("蛇吞象");
}
public void pa() {
System.out.println("我要爬走");
}
}
public class Master { //主人类
public void eat(Animal animal) {
System.out.println("mater喂食");
animal.eat();
}
}
//使用父类作为方法返回值实现多态
import java.util.Scanner;
public class Petshop { //petshop类
Scanner sc=new Scanner(System.in);
public Animal sell (int num) {
Animal animal=null;
if (num==1) {
animal=new Dog();
}else if (num==2) {
animal=new Cat();
}else if (num==3) {
animal =new Fish();
}else {
animal =new Snake();
}
return animal;
}
public void shouMenu() { //显示菜单
System.out.println("狗-1 猫-2 鱼-3 蛇-4");
System.out.println("请输入数字");
int num1=sc.nextInt();
Animal animal=sell(num1);
Master m=new Master();
m.eat(animal);
if (animal instanceof Dog) {
Dog g=(Dog) animal;
g.eat();
}else if(animal instanceof Cat) {
Cat c=(Cat)animal;
c.cry();
}else if(animal instanceof Fish) {
Fish f=(Fish)animal;
f.swim();
}else if(animal instanceof Snake) {
Snake s=(Snake)animal;
s.pa();
}
}
}
public class Text { //测试类
public static void main(String[] args) {
Petshop p=new Petshop();
p.shouMenu();
}
}
3.4instance of关键字
- 向下转型前,应判断引用中的对象真实类型,保证类型转换的正确性。
- 语法:父类引用 instance of 类型 //返回boolean类型结果
代码:
public class Animal {
public void eat() {
System.out.println("吃吃吃");
}
}
public class Cat extends Animal{
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("吃喵粮");
}
}
public class Dog extends Animal{
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("吃狗粮");
}
}
public class Test {
public static void main(String[] args) { //输出:吃狗粮
Animal a=new Dog();
if (a instanceof Dog) {
Dog dog=(Dog)a;
dog.eat();
}else if(a instanceof Cat) {
Cat cat=(Cat)a;
cat.eat();
}
}
}