JavaSE基础篇 | 面向对象三大基本特征【继承】

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 JavaSE基础篇 | 面向对象三大基本特征【继承】,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

目录

🏀继承的用法

🥅继承的相关特性

🥅通过子类对象调用继承过来的方法

🥅什么时候使用继承

🥅println方法的解释

🥅Object类的toString方法


🏀继承的用法

🥅继承的相关特性

❤️什么是继承,有什么用?
    ⭐️继承:在现实世界当中也是存在的,例如:父亲很有钱,儿子不用努力也很有钱。
    ⭐️继承的作用:
       (1)基本作用子类继承父类,代码可以得到复用。
       (2)主要作用因为有了继承关系,才有了后期的方法覆盖和多态机制。

❤️继承的相关特性
       ⭐️① B类继承A类,则称A类为超类(superclass)、父类、基类,
                                    ​​​​​​​        ​​​​​​​   B类则称为子类(subclass)、派生类、扩展类。  
            我们平时说的比较多的是:父类(superclass)和子类(subclass)。 

            class A{}
            class B extends A{}

      ⭐️② java 中只支持单继承,不支持多继承,C++中支持多继承,这也是 java 体现简单性的一点。换句话说,java 中不允许这样写代码:class B extends A,C{ } 这是错误的

      ⭐️③ 虽然 java 中不支持多继承,但有的时候会产生间接继承的效果!
           例如:class C extends B,class B extends A,也就是说,C 直接继承 B,B 直接继承 A;其实 C 就是间接继承 A。

      ⭐️④ java 中规定,子类继承父类,除构造方法不能继承之外,剩下都可以继承但是私有的属性无法在子类中直接访问(父类中private修饰的不能在子类中直接访问;可以通过间接的手段来访问,例如:调用setter and getter方法进行访问)

      ⭐️⑤ java 中的类没有显示的继承任何类,则默认继承 Object类,Object类是java 语言提供的根类(老祖宗类),也就是说,一个对象与生俱来就有 Object类型中所有的特征。

      ⭐️⑥ 继承也存在一些缺点,例如:CreditAccount 类继承 Account 类会导致它们之间的耦合度非常高Account 类发生改变之后会马上影响到 CreditAccount 类

❤️例1:不使用继承,代码臃肿

⭐️下面两个类之间有很多代码都是重复的,这就造成代码的臃肿!代码没有得到重复利用;
 在同一个类中无参的构造方法,可以通过this()来调用有参的构造方法,让代码得到复用!
 在不同类中不同类之间让代码得到重复使用呢?这就需要继承!

public class ExtendsTest01{
	public static void main(String[] args){
//3.1 创建普通账户
		Account act = new Account();
		act.setActno("1111111");
		act.setBalance(10000);
		System.out.println(act.getActno() + ",余额" + act.getBalance());

//3.2 创建信用账户
		CreditAccount ca = new CreditAccount();
		ca.setActno("2222222");
		ca.setBalance(-10000);
		ca.setCredit(0.99);
		System.out.println(ca.getActno() + ",余额" + ca.getBalance() + ",信誉度" + ca.getCredit());
	}
}

//1. 银行账户类;账户的属性:账号、余额,就比上面对一个属性
class Account{
	//1.1 属性
	private String actno;
	private double balance;

	//1.2 构造方法
	public Account(){
	
	}
	public Account(String actno, double balance){
		this.actno = actno;
		this.balance = balance;
	}

	//1.3 setter and getter
	public void setActno(String actno){
		this.actno = actno;
	}
	public String getActno(){
		return actno;
	}
	public void setBalance(double balance){
		this.balance = balance;
	}
	public double getBalance(){
		return balance;
	}
}

//2. 其它类型的账户:信用卡账户;账号、余额、信誉度
class CreditAccount{
	//2.1 属性
	private String actno;
	private double balance;
	private double credit;

	//2.2 构造方法
	public CreditAccount(){
	
	}

	//2.3 setter and getter方法
	public void setActno(String actno){
		this.actno = actno;
	}
	public String getActno(){
		return actno;
	}
	public void setBalance(double balance){
		this.balance = balance;
	}
	public double getBalance(){
		return balance;
	}

	public void setCredit(double credit){
		this.credit = credit;
	}
	public double getCredit(){
		return credit;
	}
	
}

❤️例2:使用继承(extends)优化代码

⭐️使用继承机制来解决代码复用问题。
继承也是存在缺点的:耦合度高,父类修改,子类受牵连

使用继承,父类中被private修饰的实列变量子类就不能直接访问了!

只能用set和get方法接口访问!

public class ExtendsTest02{
	public static void main(String[] args){
		// 创建普通账户
		Account act = new Account();
		act.setActno("1111111");
		act.setBalance(10000);
		System.out.println(act.getActno() + ",余额" + act.getBalance());

		// 创建信用账户
		CreditAccount ca = new CreditAccount();
		ca.setActno("2222222");
		ca.setBalance(-10000);
		ca.setCredit(0.99);
		System.out.println(ca.getActno() + ",余额" + ca.getBalance() + ",信誉度" + ca.getCredit());
	}
}

//1. 银行账户类;账户的属性:账号、余额
class Account{ // 父类
	//1.1 属性
	private String actno;
	private double balance;

	//1.2 构造方法
	public Account(){
	
	}
	public Account(String actno, double balance){
		this.actno = actno;
		this.balance = balance;
	}

	//1.3 setter and getter
	public void setActno(String actno){
		this.actno = actno;
	}
	public String getActno(){
		return actno;
	}
	public void setBalance(double balance){
		this.balance = balance;
	}
	public double getBalance(){
		return balance;
	}
}

//2. 其它类型的账户:信用卡账户;账号、余额、信誉度
class CreditAccount extends Account{ //子类

	//2.1 属性
	private double credit;

	//2.2 构造方法
	public CreditAccount(){
	
	}

	public void doSome(){

//重点:使用继承,被private修饰的实列变量就不能直接访问了!只能用set和get方法接口访问!
		System.out.println(actno);// 直接访问,是错误的
		System.out.println(getActno());// 间接访问,可以,这里省略了this.
	}

	//2.3 setter and getter方法
	public void setCredit(double credit){
		this.credit = credit;
	}
	public double getCredit(){
		return credit;
	}
	
}

❤️例3:默认继承和间接继承

(1)默认继承Object类,例如:class A就代表class A extends Object。

(2)间接继承:Z直接继承了Y,Y又继承X,所以Z间接继承了X。

(3)一个子类只能有一个父类,但是一个父类可以被多个子类继承。

//1. 单继承
class A // 默认继承Object类class A extends Object
{
}

class C extends A
{
}


//2.多继承 语法错误
// java只允许单继承。不允许多继承。java是简单的。C++支持多重继承。
class E extends A, B  //err
{
}

//3.间接继承:Z直接继承了Y,Y又继承X,所以Z间接继承了X
class X //默认继承Object类
{
}

class Y extends X
{
}

class Z extends Y
{
}
/*
	Z继承了Y
	Y继承了X
	X继承了Object
	Z对象具有Object对象的特征(基因)。
	Object是所有类的超类。老祖宗。类体系结构中的根。
	java这么庞大的一个继承结构,最顶点是:Object
*/

//4.一个父类可以被多个子类继承
class X //默认继承Object类
{
}

class Y extends X
{
}

class M extends X
{
}

🥅通过子类对象调用继承过来的方法

❤️例1:

测试:子类继承父类之后,能使用子类对象调用父类方法吗?
“能使用子类对象调用父类方法”;本质上,子类继承父类之后,是将父类继承过来的方法归为自己所有。实际上调用的也不是父类的方法,是他子类自己的方法(因为已经继承过来了就属于自己的)  

public class ExtendsTest04{
	public static void main(String[] args){
		// 创建子类对象
		Cat c = new Cat();
		// 调用方法----没问题
		c.move();
		// 通过子类对象访问name----没问题
		System.out.println(c.name);
	}
}

// 父类
class Animal{
	// 名字(先不封装)
	String name = "XiaoHua"; //默认值不是null,给一个XiaoHua
	// 提供一个动物移动的方法
	public void move(){
		System.out.println(name + "正在移动!");
	}
}

// Cat子类
// Cat继承Animal,会将Animal中所有的全部继承过来。
class Cat extends Animal{
}

🥅什么时候使用继承

❤️测试:子类继承父类之后,能使用子类对象调用父类方法吗?
    ⭐️答:可以,因为子类继承了父类之后,这个方法就属于子类了

❤️在实际开发中,满足什么条件的时候,我可以使用继承呢?
    ⭐️凡是采用“is a”能描述的,都可以继承    

   例如:
            Cat is a Animal:猫是一个动物
            Dog is a Animal:狗是一个动物
            CreditAccount is a Account:信用卡账户是一个银行账户
            ....

❤️假设以后的开发中有一个A类,有一个B类,A类和B类确实也有重复的代码,那么他们两个之间就可以继承吗?
答:不一定,还是要看一看它们之间是否能够使用is a来描述。例如:

  class Customer{ // 客户
                String name; // 名字
                // setter and getter
            }

  class Product{ // 产品
                String name; // 名字
                // setter and getter
            }

  class Product extends Customer{ // 客户是一个产品(不对)
            
            }
           //以上的继承就属于很失败的。因为:Product is a Customer,是有违伦理的。

         

🥅println方法的解释

 ⭐️任何一个类,没有显示继承任何类,默认继承Object,那么Object类当中有哪些方法呢?老祖宗为我们提供了哪些方法?
 ⭐️java为什么比较好学呢?
是因为Java内置了一套庞大的类库,程序员不需要从0开始写代码,程序员可以基于这套庞大的类库进行“二次”开发。(开发速度较快,因为JDK内置的这套库实现了很多基础的功能)

 ⭐️例如:String是SUN编写的字符串类、System是SUN编写的系统类,这些类都可以拿来直接使用。       
 ⭐️JDK源代码在什么位置?例如我的:C:\Program Files\Java\jdk-13.0.2\lib\src.zip     
 ⭐️你现在能看懂以下代码了吗?
         System.out.println(“Hello World!”);
         (1)System.out 中,out后面没有小括号,说明out是变量名
         (2)System是一个类名,直接使用类名System.out,说明out是一个静态变量。
         (3)System.out 返回一个对象然后采用“对象.”的方式访问println()方法     
 ⭐️System.out.println(引用);当直接输出一个“引用”的时候,println()方法会先自动调用“引用.toString()”,然后输出toString()方法的执行结果

public class Test{
	// 静态变量
	static Student stu = new Student();
	// 入口
	public static void main(String[] args){
		//合并代码
		Test.stu.exam();
        //拆分为两行
		Student s = Test.stu;
		s.exam();
		System.out.println("Hello World!");
	}
}

class Student{

	// 实例方法
	public void exam(){
		System.out.println("考试。。。。。");
	}
}

🥅Object类的toString方法

通过源码进行分析:

public String toString() {
        return getClass().getName() + “@” + Integer.toHexString(hashCode());
}

①getClass().getName()是获取当前的类名

②@就是一个普通的@符号

③Integer.toHexString(hashCode())是内存地址经过“哈希算法”得出的十六进制结果

//默认继承Object,Object类中有哪些方法呢?可以通过源码进行简单解读:
/*
public class Object {
	 
	 // 注意:当源码当中一个方法以“;”结尾,并且修饰符列表中有“native”关键字
	 // 表示底层调用C++写的dll程序(dll动态链接库文件)
    private static native void registerNatives();

	 // 静态代码块
    static {
		  // 调用registerNatives()方法。
        registerNatives();
    }

	 // 无参数构造方法
    @HotSpotIntrinsicCandidate
    public Object() {}

	 // 底层也是调用C++
    @HotSpotIntrinsicCandidate
    public final native Class<?> getClass();

	 // 底层也是调用C++
    @HotSpotIntrinsicCandidate
    public native int hashCode();

	 // public是公开的
	 // boolean 是方法的返回值类型
	 // equals 是一个方法名:相等
    public boolean equals(Object obj) {
		 //方法体
       return (this == obj);
    }
    
	 // 已有对象a,想创建一个和a一模一样的对象,你可以调用这个克隆方法。
	 // 底层也是调用C++
    @HotSpotIntrinsicCandidate
    protected native Object clone() throws CloneNotSupportedException;

	 // public表示公共的
	 // String 是返回值类型,toString()方法执行结束之后返回一个字符串。
	 // toString 这是方法名。
	 // () 表示形参个数为0
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

    @HotSpotIntrinsicCandidate
    public final native void notify();

    @HotSpotIntrinsicCandidate
    public final native void notifyAll();

    public final void wait() throws InterruptedException {
        wait(0L);
    }

    public final native void wait(long timeoutMillis) throws InterruptedException;

    public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
        if (timeoutMillis < 0) {
            throw new IllegalArgumentException("timeoutMillis value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {
            timeoutMillis++;
        }

        wait(timeoutMillis);
    }
    @Deprecated(since="9")
    protected void finalize() throws Throwable { }
}
*/

//-------------代码测试toString()方法
public class ExtendsTest05 {

	// ExtendsTest05默认继承Object
	// ExtendsTest05类当中是有toString()方法
	// 不过toString()方法是一个实例方法,需要创建对象才能调用。
	/*
	public String toString() {
		return getClass().getName() + "@" + Integer.toHexString(hashCode());
	}
	*/

	public static void main(String[] args){

		// 分析这个代码可以执行吗?不会
		//ExtendsTest05.toString();

		// 先new对象
		ExtendsTest05 et = new ExtendsTest05();
		String retValue = et.toString();

		// 2f92e0f4 可以“等同”看做对象在堆内存当中的内存地址。
		// 实际上是内存地址经过“哈希算法”得出的十六进制结果。
		System.out.println(retValue); // ExtendsTest05@2f92e0f4

		// 创建对象
		Product pro = new Product();

		String retValue2 = pro.toString();
		System.out.println(retValue2); // Product@5305068a

		// 以上两行代码合并为一行!!!
		System.out.println(pro.toString()); //Product@5305068a

		// 如果直接输出“引用”呢?会自动调用toString方法
		System.out.println(pro); //Product@5305068a

		// Product@5305068a
		System.out.println(pro); // println方法会自动调用pro的toString()方法。
	}
}

class Product{ //默认继承Object类,有toString()方法
	/* 
	public String toString() {
		return getClass().getName() + "@" + Integer.toHexString(hashCode());
	}
	*/
}

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

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/128495.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!