面向对象编程基本部分——java三大特性详解
Posted 卷扬机
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象编程基本部分——java三大特性详解相关的知识,希望对你有一定的参考价值。
本文是基于楼主学习韩顺平老师java课后的笔记整理而来 分享出来 希望能跟大家一起交流 共同进步~
为了秋招 冲冲冲!
绪论
java有一个重要的特性是面向对象(oop)
这是它与其他语言重要的差别之一 也是它如此受市场欢迎的重要原因
本文我们就来简单说说 封装继承多态这三大面向对象重要特征
封装
一 封装是什么
简而言之,封装就是把抽象出来的数据【属性】和对数据的操作【方法】封装在一起
数据被保护在内部 程序的其他部分只有通过被授权的方法 才能对数据进行操作
类似电视机 中我们只能用遥控器控制声音大小 亮度增减 但是并不知道它内部是怎么实现的 也不用知道
这点就可以看出面向对象的好处了 不同于c面向过程注重功能的具体实现 java拥有非常强大的类库 大大提高了程序员的创造力 不用再费很多心思去造轮子 更多的是分析需求 直接调用方法即可 毕竟语言和框架只是一种工具罢了 功能的实现才是最重要的
二 为什么需要封装
封装可以隐藏实现细节 方法 调用
因为不知道类里面是怎么实现的 我们只需要调动即可 做到了一定程度的封闭安全性
封装可以对数据进行验证 保证安全合理
比如 对名字进行初始化 规定名字字数不能超过六个字 我们可以在内部进行规定
三 怎么封装
第一步将属性进行私有化private
保证封装安全性
第二步提供一个公共的set方法 用于对属性判断并赋值
对对象进行赋值
第三步提供一个公共的get方法用来获取属性的值
四 example
创建程序 在其中定义两个类 Account和AccountTest类体会java的封装性
1.Account类必须具有属性 姓名(长度为2 3 4位) 余额(必须大于20) 密码(必须是六位) 如果不满足 则给出提示信息 并给出默认值
2.通过setxx的方法给Account的属性赋值
3.在AccountTest中测试
public class Account {
public static void main(String[] args) {
AccountTest a = new AccountTest("wuyifan",15,"1234567");
System.out.println( a.toString());
}
}
class AccountTest{
String name;
double salary;
String password;
public AccountTest(String name, double salary,String password){
setName(name);
setSalary(salary);
setPassword(password);
}
public String getName() {
return name;
}
public void setName(String name) {
if(name.length()>=2&&name.length()<=4){
this.name = name;}
else{
System.out.println("wrong name");
this.name = "wu";
}
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
if(salary>20){
this.salary = salary;
}
else{
System.out.println("wrong salary");
this.salary=30;
}
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
if(password.length()==6){
this.password = password;
}
else{
System.out.println("wrong password");
this.password ="123456";
}
}
@Override
public String toString() {
return "AccountTest{" +
"name='" + name + '\\'' +
", salary=" + salary +
", password='" + password + '\\'' +
'}';
}
}
五 细节
访问修饰符 分为四大类 public 默认 protected private
对方法和属性进行操作时 要遵循访问修饰符的访问范围
六 总结
封装是面向对象的基础 大家只要知道封装是将一个类的方法和属性都封装在一起就可以了 不用咬文嚼字
继承
一 继承是什么?
继承是指 当多个类存在相同的属性时 可以从这些类中抽象出父类 在父类中定义这些相同的属性和方法 所有的子类不需要重新定义这些属性和方法 只需要通过extends来声明继承父类即可
二 为什么要使用继承?
我们编写了两个类 一个小学生类 一个研究生类 两个类的属性和方法有很多是相同的 比如说 小学生有名字 初中生也有名字 小学生要学习 初中生也要学习 怎么办 如果在两个类中分别写它们共有的方法和属性 则重复代码太多 过于冗余 所以我们可以使用一个父类 写一遍 然后子类继承只需要写子类特有的方法和属性即可 大大提高了代码的复用性和整洁度
三 继承的使用方法
class 子类 extends 父类{
//extends关键字
}
四 example
父类 Student.java
package com.shijiu.test;
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);
}
}
子类 Pupil.java
package com.shijiu.test;
public class Pupil extends Student {
public void testing(){
System.out.println("小学生"+name+"正在考试");
}
}
子类 Graduate.java
package com.shijiu.test;
public class Graduate extends Student {
public void testing(){
System.out.println("大学生"+name+"正在考试");
}
}
五 继承的注意事项
一 子类继承了父类所有的属性和方法 但是私有属性不能在子类直接访问 非私有属性可以直接访问 要通过(父类提供)公共的方法(get set 方法)去访问
二 子类必须调用父类的构造器完成父类的初始化
三 当创建子类对象时 不管使用子类的哪个构造器 默认情况下总会去调用父类的无参构造器 如果父类没有提供无参构造器 则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作 否则编译不会通过
四 如果希望指定去调用父类的某个构造器 则显式的调用一下 super(参数列表)
五 super在使用的时候 必须放在构造器第一行
class A{
private String name;
public A(String name) {
this.name = name;
}
}
class B extends A{
public B(String name) {
super(name);
}
}
六 子类最多只能继承一个父类(直接继承) java是单继承机制 但可以用接口实现多继承
六 继承的本质探究
public class Pupil extends Student {
public static void main(String[] args) {
Son son = new Son();
//一级一级向上查找
System.out.println(son.name);//大头儿子
System.out.println(son.age);//39
System.out.println(son.hobby);//旅游
}
}
class GrandPa{
String name = "大头爷爷";
String hobby = "旅游";
}
class Father extends GrandPa{
String name = "大头爸爸";
int age = 39;
}
class Son extends Father{
String name = "大头儿子";
}
本质上我们来看 继承即是一种查找 从子类开始向上查找 直到Object类 查找它的属性和方法
方法的重载和重写
重载
方法重载(Overloading):在一个类中,如果两个方法的方法名和相同,参数列表不同,那么这个方法就被定义为方法重载。
因此,只要在同一个类中,两个方法的方法名相同,参数列表不同即可,与其权限修饰符、返回值类型、方法无关。
class B extends A{
public B(String name) {
super(name);
}
public int m1(int a){
return a;
}
public int m1(int a,int b){
return a+b;
}
}
重写
方法重写:子类可以定义新的特征,当子类需要修改父类的一些方法进行扩展,增大功能,程序设计者常常把这样的一种操作方法称为重写,也叫称为覆写或覆盖。
class A{
private String name;
public A(String name) {
this.name = name;
}
public int m1(int a){
return a;
}
}
class B extends A{
public B(String name) {
super(name);
}
@Override
public int m1(int a) {
return super.m1(a);
}
}
注意
重写中 父类的参数列表和子类中的参数列表 和父类中的返回类型和子类中的返回类型必须一样 否则不构成重写 构成重载 并且子类的访问修饰符范围不能比父类的访问修饰符范围更小
多态
一 多态是什么?
方法或者对象具有多种状态 是面向对象的第三大特征 多态是建立在封装和继承的基础上的
对方法:方法的重载体现多态 很好理解 你输入的参数不同 自然调用的方法不同
方法的重写依然体现多态 不同的对象调用就会产生不同的效果
对对象:一个对象的编译类型和运行类型可以不一样 编译类型在定义时 就确定了 不能再改变
运行类型可以改变 编译类型看等号的左边 运行类型看等号的右边
Animal animal = new Dog();
//annimal 编译类型是 Animal 运行类型是Dog
二 多态的两种实现方式
前提:两个对象(类)存在继承关系
向上转型
1.本质:父类的引用指向了子类的对象
2.语法:父类类型 引用名 = new 子类类型();
3.特点:编译类型看左边 运行类型看右边
可以调用父类中的所有成员(需遵守访问权限)
不能调用子类中特有成员
最终运行效果看子类的具体实现
编译阶段能调用哪些成员是由编译类型来决定的
public class Pre {
public static void main(String[] args) {
At at = new Bt("jack");
at.m1();
}
}
class At{
private String name;
public At(String name) {
this.name = name;
}
public void m1(){
System.out.println("这是父类的方法");
}
}
class Bt extends At{
public Bt(String name) {
super(name);
}
@Override
public void m1() {
System.out.println("这是子类的方法");
}
}
当向上转型之后,父类引用变量可以访问子类中属于父类的属性和方法,但是不能访问子类独有的属性和方法。
向下转型
并不是所有的对象都可以向下转型,只有当这个对象原本就是子类对象通过向上转型得到的时候才能够成功转型。
At at = new Bt("jack");
Bt bt = (Bt) at;
bt.m1();
语法 子类类型 引用名 = (子类类型) 父类引用
只能强转父类的引用 不能强转 父类的对象
可以调用子类类型中所有的成员
三 多态的细节
属性没有重写之说 属性的值看编译类型
Base base = new sub();
System.out.println(base.count);
看等号左边 左边的类中count是多少就是多少
instanceof比较操作符 判断对象运行类型是否为类的子类或者是否为该类父类的类型
System.out.println(b instanceof A)
访问属性 看编译类型 访问方法 看运行类型
四 多态数组
数组的定义类型为父类类型 里面保存的实际元素类型为子类类型 可以依据不同的运行类型调用不同的方法
应用案例 现有一个继承结构 要求创建一个Person对象 2个Student对象和2个Teacher对象 统一放在数组中 并调用say方法
父类 人类
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+'\\t'+age;
}
}
子类学生类
package com.shijiu.poly;
public class Student extends Person {
private double score;
public Student(String name, int age, double score) {
super(name, age);
this.score = score;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
@Override
public String say() {
return super.say()+"score"+score;
}
public void study(){
System.out.println("学生"+getName()+"正在学java");
}
}
子类教师类
package com.shijiu.poly;
public class Teacher extends Person {
private double salary;
public Teacher(String name, int age, double salary) {
super(name, age);
this.salary = salary;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String say() {
return super.say()+'\\t'+"salary"+salary;
}
public void teach(){
System.out.println("老师"+getName()+"正在上课");
}
}
主方法
package com.shijiu.poly;
public class PolyArray {
public static void main(String[] args) {
Person[] persons = new Person[5];
persons[0] = new Person("jack",20);
persons[1] = new Student("tom",20,89);
persons[2] = new Student("smith",20,60);
persons[3] = new Teacher("scott",30,20000);
persons[4] = new Teacher("servt",35,50000);
for (int i = 0; i < persons.length; i++) {
System.out.println(persons[i].say());
if(persons[i] instanceof Student){
((Student) persons[i]).study();
}
if(persons[i] instanceof Teacher){
//向下转型
((Teacher) persons[i]).teach();
}
}
}
}
结语
大二了 也二十岁了 不是似懂非懂的少年了 也该为自己的未来做准备了 承担一些自己应该担当的责任了 不然呢 等到毕业找不到工作再努力吗 回家靠爸妈养着?前几天看到一个大佬拿了阿里的offer 对就是路飞学长 非常羡慕 看了他的文章 觉得这一路走来学长非常的努力和不容易 十分钦佩 每个人都是从小白过来的 他们可以我相信我也可以 希望我自己能够见贤思齐 认真备战 争取能在毕业前交上属于自己的满意答卷 全力以赴 不留遗憾。
努力 为了自己想要的生活!
数据结构+java技术栈+力扣刷题
第一篇博客写的不是特别好 见谅 以后会不断进步的 求大佬们三连!
以上是关于面向对象编程基本部分——java三大特性详解的主要内容,如果未能解决你的问题,请参考以下文章