软件构造--Chapter7总结

Object-Oriented Programming(OOP)

Basic concepts:object,class,attribute,and method

真实的世界中的对象有两大特征,即states、behaviors。例如狗有states(姓名、颜色、饥饿等)和behaviors(狂吠、摇尾巴等)
Object是state和behavior的集合。而在Java中,state对应为field,而behavior对应method。
在这里插入图片描述
每一个对象对对应一个类,类中确定了Fields和Methods。其中,静态变量/方法(即由static修饰的)不需要实例化,通过类名.变量/方法即可调用。而静态方法无法直接调用非静态成员。

Interface and Enumerations

Java的接口是设计和表达ADT的一种有用的语言机制,其实现为实现该接口的类。
在接口中只有方法定义,没有实现(Java8之后接口的静态方法可以有实现)、接口之间可以继承与扩展、一个类可以实现多个接口(具备多个接口中的方法),同样的,一个接口可以有多个实现类。

public interface MyString{
	/** 
	 * @param b a boolean value
	 * @return string representation of b,either "true" or "false"
	 */
	public static MyString valueOf(boolean b){
		return new FastMyString(true);
	}
}

另外,接口中default修饰的方法可以实现接口中某些统一的功能,在各个类中重复实现。default以增量式的为接口额外增加的功能而不破坏已实现的类。

public interface Example{
	default int method1(int a){...}
	static int method2(int b){...}
	public int method3();
}

public class C implements Example{
	@Override
	public int method3(){...}
	
	public static void main(String[] args){
		Example.method2(2);
		C c = new C();
		c.method1(1);
		c.method3();
	}
}

接口中default、static使用如上。
接口用来确定ADT规约,而类是通过接口来实现ADT(当然也可以不使用接口实现ADT)

Encapsulation and information hidding

将设计良好的模块与设计不良的模块区分开来的一个最重要的因素是,它对其他模块隐藏内部数据和其他实现细节的程度。好的设计代码能够隐藏所有的实现细节。
信息隐藏能够解耦系统中的类、加速系统的发展、减轻维护的负担、能够有效地调整项目,还能够提升软件的可复用性。
使用接口可以做到信息隐藏。使用接口类型声明变量,client仅仅使用接口中定义的方法,无法直接访问相关属性。但是client还是可以访问其他非接口成员。

Visibility modifiers for members

大致有四种成员修饰语,即private、protected、缺省和public
在这里插入图片描述
通过成员修饰语,给client提供他们需要的方法,其他成员以private修饰,不进行提供。

Inheritance and Overriding

Overriding

Rewriteable Method可以允许对方法进行重新实现,而Strict inheritance对应的,子类只能添加新方法,无法重写超类中的方法。(final修饰的方法无法被重写)

class Device{
	int serialnr;
	public final void help(){...}
	public void setSerialNr(int n){
		serialnr = n;
	}
}

class Valve extends Device{
	Positon s;
	public void setSerialNr(int n){
		...
	}
}

在上述示例中,help方法就不能被重写,而setSerialNr方法可以被重写。
重写,对应的父类和子类签名一致(使用@Override编译器会自动检查)、参数列表一致。在实际执行时调用哪种方法,是在运行时决定的。
父类型中被重写函数体不为空,意味着对其大多数子类型,该方法可以被直接复用的;对某些子类型来说有特殊性,故重写父类型中的函数,实现自己的特殊要求。
如果父类型中的某个函数实现体为空,意味着其所有子类型都需要此功能,但是有差异,缺少共性,在每个子类中都需要重写。
重写之后,可以通过super()复用父类中的函数功能。

Abstract Class

抽象方法只有定义没有实现,而抽象类只需要存在一个方法只有定义没有实现,但是抽象类不能够实例化(无法new生成对象),需要将未实现的方法都实现才能new。
如果有些操作所有子类型共有但是有差异,可以在父类型使用抽象方法,由各个子类型重写实现;有些子类型有而其他子类型没有的操作,需要在具体的子类型定义、实现。
特殊地,Interface是只有抽象方法的抽象类。

Polymorphism,subtyping and overloading

Three Types of Polymorphism

1.特殊多态:一个方法可以有多个同名的实现(重载)
2.参数化多态:一个类型名字可以代表多个类型(泛型编程)
3.子类型多态:一个变量名字可以代表多个类的实例(子类型)

Ad hoc polymorphism and Overloading

当一个函数在几个不同的类型上工作(可能不会显示出共同的结构)并且可能以不相关的方式对每个类型进行操作时,就会获得特殊多态性。

public class OverloadExample{
	public static void main(String args[]){
		System.out.println(add("C","D"));
		System.out.println(add("C","D","E"));
		System.out.println(add(2,3));
	}
	public static String add(String c,String d){
		return c.concat(d);
	}
	public static String add(String c,String d,Sting e){
		return c.concat(d).concat(e);
	}
	public static int add(int a,int b){
		return a+b;
	}
} 

重载方法有统一的名字,把相近的方法统一,但是参数列表必须不同。
重载属于静态多态,根据参数列表进行最佳匹配,是静态类型检查,在编译阶段具体决定执行哪个方法。(重写属于动态检查)
其中静态检查,只看声明不看实例化。

A a = new B();

在a被检查时,其类型为A,而不是B。
重载的规则:
1.必须有不同的参数列表;
2.可以有不同的返回值类型;
3.可以有不同的访问权限;
4.可以有不同的异常;
5.一个方法可以在同一个类内重载,也可以在子类中重载。

public void changeSize(int size,String name,float pattern){}

1.public void changeSize(int size,String name){}
2.public int changeSize(int size,float pattern){}
3.public void changeSize(float pattern,String name){}
4.public void changeSize(int length,String pattern,float size){}
5.public boolean changeSize(int size,String name,float pattern){}

在上述示例中,4、5不属于方法重载。
另外,重载也可以发生在父类和子类之间。
下面是几个重载、重写相关的调用示例。
在这里插入图片描述
在这里插入图片描述

Parametric polymorphism and Generic programming

参数多态性是指方法针对多种类型时具有同样的行为(多种类型应该有通用结构),此时可使用统一的类型变量表达多种类型。
在运行时根据具体指定类型确定具体类型(编译成class文件时,会用指定类型替换类型变量),在Java中称为泛型。
泛型编程中的数据类型和函数是根据待定指定的类型编写的,随后在需要时根据参数提供的特定类型实例化。
使用<>帮助声明泛型类型,例如

public interface List<E>
public class Entry<KeyType,ValueType>
List<Integer> ints = new ArrayList<Integer>();

使用泛型变量有三种类型,即泛型类、泛型接口和泛型方法。
1.泛型类:
类中如果声明了一个或者多个泛型变量,则为泛型类。这些类型变量成为类的类型参数。示例如下:

class ClassName <T,E,...>{
	private T var;
	...
}

2.泛型接口:
接口中如果声明了一个或者多个泛型变量,则为泛型接口。这些类型变量成为接口的类型参数。示例如下:

interface InterfaceName <T,E,...>{
	public T methodName();
	...
}

另外,常常使用的Set类型也是一个泛型接口。
泛型接口可以对应非泛型的实现类、也可以对应泛型的实现类。

Subtyping Polymorphism

一个类只有一个父类,但是可以实现多个接口。
B是A的子类型表示每个B都是A,每个B都满足A的规约。如果B的规格至少与a的规格一样强,即子类型规约不能弱化超类型的规约。
子类型多态,不同类型的对象可以统一的处理而无需区分。

Some important Object methods in Java

Object是所有Java的基类,有三个主要的方法,即equals()、hashCode()和toString()。
equals()方法不重写默认比较内存地址是否相同;toString()方法不重写默认显示内存地址。
根据需要进行相应的方法重写,其中不可变类型需要三个方法都重写,而可变类型只需要重写toString()方法即可。在重写上述方法时,可以根据IDEA提供的便利,自动生成对应方法,再按照需求进行微调即可。

Designing good classes

设计不可变类型的类有如下的优势:
1.Simplicity – 简单
2.Inherently Thread-Safe – 固有线程安全
3.Can be shared freely – 可以自由共享
4.No need for defensive copies – 无需防御性拷贝
5.Excellent building blocks – 优秀的构成要素
实现不可变类型的类,不能提供mutators、要确保所有的方法不能被重写、所有的fields被final和private修饰、确保可变成分的安全(避免表示泄露)以及实现toString()、hashCode()、clone()、equals()等方法。
尽可能让类是不可变的,除非有需要是可变类型,即使是可变类型的类,要最小化其可变性。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深海质粒ABCC9

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值