JAVA 基础学习之 封装 继承 多态三大特性

封装

 

为什么要封装? 

 

现实生活中封装概念的引入

台式机电脑:机箱[ 主板 显卡  内存  电源  硬盘…]

机箱是保护里面硬件的安全

 

以上示例的总结:

都是通过物理层面封装的操作,达到从控制访问的目的

Java中为什么要封装?

因为可以任意修改对象的成员变量值不安全

案例:
 



/**

 * 账户类

*/

public class Account {

/**账户名 */

String name;

/**账户余额 */

double money;

public Account() {

}

}





/**

 * 封装测试类

 */

public class AccountTest {



public static void main(String[] args) {

//创建了一个对象

Account cang = new Account();

//给对象赋值

cang.name = "机箱";//初始值

cang.money = 10000000.00;//初始值



//没有封装,可以任意修改值

cang.name = "随便";//没有封装,可以任意修改姓名,不安全

cang.money = -1000000.00;//没有封装,可以任意修改余额,不安全

}



}

 

封装作用

封装是为了保护内部数据的安全:

1. 不希望在外部类中随意访问类中的成员变量

2. 达到权限要求的才能访问。

3. 只是获取数据的时候,例如 单例模式

怎么封装

如何控制程序中的访问 ?

通过给类中的成员(字段,方法,构造方法)添加访问权限修饰符来实现封装(访问控制)

什么是访问权限:简单的认为访问权限就是不同级别的人能够干不同级别的事,不同级别的人能看到的页面是不同的

例子:比如做一个系统,不同人登录进去的访问权限不一样;

访问权限修饰符: 

public 最大权限,被其修饰的成员,在任意目录下,都可以访问到 (所有类)

protected 在同包类和子类中都可以访问

默认不写 只能在同包类中访问

private 只能在当前类中访问

封装的步骤

1. 私有化成员变量(用private修饰成员变量)

2. 为每一个成员变量提供合理的

  getXxx()方法 获取成员变量的值,如果当前成员变量类型是boolean类型,将getXxx()改为 isXxx()

  setXxx(...)方法 设置成员变量的值

3. 提供一个无参构造

4. 该类用public修饰

封装案例:



/**

*  账户类

*/

public class Account {// 4. 该类用public修饰

/**账户名 1. 私有化成员变量(用private修饰成员变量) */

private String name;



/**账户余额  1. 私有化成员变量(用private修饰成员变量) */

private double money;



/**是否是VIP账户   1. 私有化成员变量(用private修饰成员变量) */

private boolean vip;



/**

 *  2. 为每一个成员变量提供合理的

 * getXxx()方法 获取成员变量的值,如果当前成员变量类型是boolean类型,将getXxx()改为 isXxx()

 *

 * setXxx(...)方法 设置成员变量的值

 * @return

 */

public String getName(){

return name;

}



/**

 *  2. 为每一个成员变量提供合理的

 * getXxx()方法 获取成员变量的值,如果当前成员变量类型是boolean类型,将getXxx()改为 isXxx()

 *

 * setXxx(...)方法 设置成员变量的值

 */

public void setName(String n){

name = n;//将n赋值给成员变量name

}



public double getMoney(){

return money;

}



public void setMoney(double m){

//可以在方法中限制权限

money = m;//将m赋值给成员变量money

}



public boolean isVip(){

return vip;

}



public void setVip(boolean v){

vip = v;//将v赋值给成员变量vip

}



/**

 *  3. 提供一个无参构造

 */

public Account() {

}



public Account(String n,double m,boolean v) {

//给成员变量赋值

name = n;

money = m;

vip = v;

}

}

封装的注意事项

1. 不是只有private才叫封装,private只是最大限度的封装而已。

2. get和set方法都是只能获取或者赋值一个成员变量

  不能set(String n,double m,boolean v)赋值3个成员变量

  3. 单一职能原则:功能最小化,不要想着一个方法写完所有的功能,因为代码复用率

继承

继承引入

 

三个类都有重复的代码,可以把这共同的代码抽出去,抽出去放到另外一个类里面;下面的3个类和上面的类需要发生一点关系(继承),上面的类叫做 父类(超类,基类,根类),下面的类叫子类(派生类,拓展类);

好处 : 提高了代码的复用性

继承作用

代码复用,提高开发效率和程序的扩展性。

Java中类继承的基本语法

① Java类中的继承的语法格式:

class A{}

class B extends A{}

A 就是B的父类、基类、根类、超类

B是A的子类、派生类、拓展类

② 验证:子类中是否可以继承到父类中的东西(通过创建子类对象来操作从父类继承的东西)

案例代码:

父类:

public class Animal {

String name;

int age;

public void eat() {

System.out.println("吃");

}

}

子类:

public class Person extends Animal{

/**

 * 人类独有方法

 */

public void coding() {

System.out.println("敲代码...");

}

}



public class Pig extends Animal{

/**

 * 猪类独有方法

 */

public void gongBaiCai() {

System.out.println("拱白菜...");

}

}



public class Bird extends Animal{

/**

 * 鸟类独有方法

 */

public void fly() {

System.out.println("飞...");

}

}



测试类:

/**

 * 继承测试类

 */

public class AnimalTest {



public static void main(String[] args) {

//创建子类对象

Person person = new Person();



Pig pig = new Pig();



//通过子类对象调用父类继承过来的成员

person.name = "张三";

person.age = 1;

person.eat();

System.out.println(person.name);

System.out.println(person.age);

//调用子类特有方法

person.coding();



pig.name = "佩奇";

pig.age = 7;

pig.eat();

System.out.println(pig.name);

System.out.println(pig.age);

//调用子类特有方法

pig.gongBaiCai();

}

}

子类可以从父类继承哪些成员?

除了构造方法不能被继承其他都可以继承过来

但是,私有化成员不能直接通过子类对象直接访问,但是可以通过继承过来的公共方法间接访问 代码如下:

public class Animal {

String str;

private int a;

static int b;

public Animal() {

System.out.println("无参构造...");

}

public Animal(int a) {

System.out.println("有参构造...");

}

public void test() {

System.out.println("普通方法");

}

public static void testStatic() {

System.out.println("静态方法..");

}

private void testPrivate() {

System.out.println("私有化方法..");

}

public int getA() {

return a;

}

public void setA(int a) {

this.a = a;

}

}



public class Person extends Animal{

/**

 * 人类独有方法

 */

public void coding() {

System.out.println("敲代码...");

}

}



测试代码:

/**

 * 测试继承哪些成员

 */

public class AnimalTest {



public static void main(String[] args) {

//创建子类对象

Person person = new Person();



//通过子类对象调用父类继承过来的普通成员变量

person.str = "张三";



//通过子类对象调用父类继承过来的私有化成员变量

// person.a = 1;//不能通过子类对象直接调用父类私有化成员



//通过子类对象调用父类继承过来的静态成员变量

// person.b = 2;//不要这样用。 这里编译的时候,会将person对象直接编译为类名的方式



//通过子类对象调用父类继承过来的普通方法

person.test();



//通过子类对象调用父类继承过来的静态方法

// person.testStatic();//不要这样用。 这里编译的时候,会将person对象直接编译为类名的方式



//通过子类对象调用父类继承过来的私有化方法

// person.testPrivate();//不能直接调用私有化方法



//子类调用可以通过父类公共方法间接调用父类中私有化的成员

person.setA(69);



int a = person.getA();

System.out.println(a);//69



//调用Object继承过来的方法

int hashCode = person.hashCode();

System.out.println(hashCode);

}



}

 

Java中类的继承特点

单继承(一个类只能够有一个直接父类)

多重继承(多层级的继承), 一个类可以有子类,子类还可以子类...  

示例:

class A{}

class B extends A{}

class C extends B{}

class D extends C{}

③ 每一个类都有一个直接父类,如果没有看到显示的继承代码,那么就隐式继承Object

 

 

多态polymorphic

什么是多态?

简单理解 : 看成一种事物多种形态

示例  :

今天晚上大家请我吃大餐 :  龙虾   喝粥  思想大餐....

           我准备买一辆车:  独轮车 自行车  拖拉机   布加迪模型....

 

Java 程序中的体现:

多态概念:

将子类对象装到父类的变量中保存(向上造型/向上转型),当父类变量调用方法的时候,如果子类重写了该方法,会直接执行子类重写之后的方法。(父类变量可以装任意类型的子类对象)。

多态案例1:

父类:

public class Animal {

int age = 1;

public void eat() {

System.out.println("吃....");

}

}



子类:

public class Person extends Animal{

int age = 2;

@Override

public void eat() {

System.out.println("吃肉...");

}



public void coding() {

System.out.println("撸代码...");

}

}



public class Pig extends Animal{

int age = 3;

@Override

public void eat() {

System.out.println("吃白菜");

}



public void gongBaiCai() {

System.out.println("拱白菜");

}

}



测试代码:

public class AnimalTest {



public static void main(String[] args) {

Animal animal = new Person();//多态的方式(向上造型/向上转型)

Animal animal2 = new Pig();//多态的方式(向上造型/向上转型)



//调用方法

animal.eat();//吃肉...   执行子类重写后的方法

animal2.eat();//吃白菜    执行子类重写后的方法



System.out.println(animal.age);//1     成员变量没有多态



// animal.gongBaiCai();//多态不能调用子类独有方法

}

}

 

多态作用:

可以屏蔽子类差异性,提高代码的扩展性

 

多态使用:

1. 向上造型/向转型

   语法:

父类类型  父类变量 = new 子类类型();

父类变量.方法();//子类若重写,则会执行子类重写后的方法

例如:

Animal animal = new Person();//多态的方式(向上造型/向上转型)

Animal animal2 = new Pig();//多态的方式(向上造型/向上转型)



//调用方法

    animal.eat();//吃肉...   执行子类重写后的方法

    animal2.eat();//吃白菜    执行子类重写后的方法

2. 向下造型/向下转型 =>就是为了调用子类特有方

 

例如:(接上面案例)

   现在需要调用子类Person中特有的方法或者调用子类Pig中特有的方法,不能调用怎么办?

这个时候就需要强制转换(向下造型/向下转型

强制转换(向下造型/向下转型语法:

数据类型 变量 = (数据类型)值/变量;

在向下造型前,必须进行类型判断,需要判断当前父类变量中装的是哪一个子类类型的对象

类型判断方式1:

   if(父类变量 instanceof 子类类型1){

//强制类型转换

子类类型1 子类变量 = (子类类型1)父类变量;

//现在就可以调用子类特有方法

子类变量.子类特有方法(...);

   }else if(父类变量 instanceof 子类类型2){

//强制类型转换

子类类型2 子类变量 = (子类类型2)父类变量;

//现在就可以调用子类特有方法

   子类变量.子类特有方法(...);

     }...

类型判断方式2:

   if(父类变量.getClass() == 子类类型1.class){

   //强制类型转换

子类类型1 子类变量 = (子类类型1)父类变量;

//现在就可以调用子类特有方法

子类变量.子类特有方法(...);

}else if(父类变量.getClass() == 子类类型2.class){

//强制类型转换

子类类型2 子类变量 = (子类类型2)父类变量;

//现在就可以调用子类特有方法

子类变量.子类特有方法(...);

}...

     如果不进行类型判断再强转,就有可能发生ClassCastException类造型异常

测试类代码如下:

public class AnimalTest {



public static void main(String[] args) {

Animal animal = new Person();//多态的方式(向上造型/向上转型)

Animal animal2 = new Pig();//多态的方式(向上造型/向上转型)

animal = new Pig();//多态的方式(向上造型/向上转型)



//调用方法

animal.eat();

animal2.eat();

System.out.println(animal.age);//1     成员变量没有多态



//如果这里需要调用Pig类中特有方法,就需要将animal强转为Pig类型

//类型判断的方式1

if (animal instanceof Pig) {//判断animal中是不是装的Pig对象,如果是才强转

Pig pig = (Pig)animal;

//调用Pig特有方法

pig.gongBaiCai();

} else if (animal instanceof Person) {

//如果这里需要调用Person类中特有方法,就需要将animal强转为Person类型

Person person = (Person)animal;

//调用Person特有方法

person.coding();

}



//类型判断的方式2

if (animal.getClass() == Pig.class) {//判断animal中是不是装的Pig对象,如果是才强转

Pig pig = (Pig)animal;

//调用Pig特有方法

pig.gongBaiCai();

} else if (animal.getClass() == Person.class) {

//如果这里需要调用Person类中特有方法,就需要将animal强转为Person类型

Person person = (Person)animal;

//调用Person特有方法

person.coding();

}

}

}


1.4 多态注意事项:

多态案例2:

父类:

public class Vip {

/**

 * 会员特权

 */

public void privilege() {

System.out.println("我有特权...");

}

}



子类:

public class Vip1 extends Vip{

/**

 * 会员特权

 */

public void privilege() {

System.out.println("我是5000元俱乐部会员");

}

public void low() {

System.out.println("我很low");

}

}



public class Vip2 extends Vip{

/**

 * 会员特权

 */

public void privilege() {

System.out.println("我是500000元俱乐部会员");

}

public void normal() {

System.out.println("我很一般");

}

}





public class Vip3 extends Vip{

/**

 * 会员特权

 */

public void privilege() {

System.out.println("我是500000000000元俱乐部会员");

}

public void great() {

System.out.println("我很NB....");

}

}



测试类:

public class VipTest {



public static void main(String[] args) {

/*

 * 模拟会员登陆的时候特权展示

 *

 */

Vip vip = new Vip2();//屏蔽子类差异性



//调用特权

vip.privilege();//调用特权方法,如果子类重写了,会执行对应子类重写后的方法



//判断当前VIP中装的子类是哪一个,展示对应的特权

if (vip instanceof Vip1) {//类型判断

//强制转换

Vip1 vip1 = (Vip1)vip;

//调用特有方法

vip1.low();

}else if (vip instanceof Vip2) {//类型判断

//强制转换

Vip2 vip2 = (Vip2)vip;

//调用特有方法

vip2.normal();

}else if (vip instanceof Vip3) {//类型判断

//强制转换

Vip3 vip3 = (Vip3)vip;

//调用特有方法

vip3.great();

}

}



}



多态案例3:

父类:

public class Dog {

public void eat() {

System.out.println("吃...");

}

}



public class Hasky extends Dog {

@Override

public void eat() {

System.out.println("狗粮..");

}

}



public class Teddy extends Dog {

@Override

public void eat() {

System.out.println("吃天吃地吃空气");

}

}





public class Tudog extends Dog {

@Override

public void eat() {

System.out.println("啃骨头。。。");

}

}





public class Person {

/*public void feedDog(Hasky dog) {

dog.eat();

}



public void feedDog(Teddy dog) {

dog.eat();

}



public void feedDog(Tudog dog) {

dog.eat();

}

如果有几万种狗,就需要写几万个方法喂狗,不可取

*/

public void feedDog(Dog dog) {//屏蔽子类差异性。写一个父类类型,所有的子类对象都可以接收

dog.eat();

}

}



测试类:

public class DogTest {



public static void main(String[] args) {

//测试喂狗案例

Hasky hasky = new Hasky();

Tudog tudog = new Tudog();

Teddy teddy = new Teddy();



Person person = new Person();

person.feedDog(hasky);

person.feedDog(tudog);

person.feedDog(teddy);

}

}

1. 成员变量没有多态

2. 不能调用子类特有的方法,如果需要调用子类特有的方法,必须进行强制类型转换(向下造型/向 下转型),向下造型需要进行子类类型判断

3. 父类变量能点(调用)出哪些成员(成员变量和方法),是由当前类和其父类决定,优先从当前类 开始查找,直到找到Object了为止,如果Object中有没有,就不能调用

4. 多态调用方法的优先级顺序为:

该优先级为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)

多态扩展练习:

代码如下:

public class A {

public String show(D obj) {

return ("A and D");

}

public String show(A obj) {

return ("A and A");

}

}



public class B extends A {

public String show(B obj) {

return ("B and B");

}

public String show(A obj) {

return ("B and A");

}

}



public class C extends B {

}



public class D extends B {

}



测试类:

public class Test {

public static void main(String[] args) {

A a1 = new A();

A a2 = new B();

B b = new B();

C c = new C();

D d = new D();



a1.show(b);// "A and A"

a1.show(c);// "A and A"

a1.show(d);// "A and D"



a2.show(b);//  B and A

a2.show(c);//  B and A

a2.show(d);// "A and D



b.show(b);// "B and B"

b.show(c);// "B and B"

b.show(d);// "A and D"

}



}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值