一种特别的面向对象设计
大约 3 分钟
一种特别的面向对象设计
我的设计的尝试
核心:
- 用一个单例来描述类,也就是伴随对象
- 类似于JavaScript原型链——成员方法和静态方法属于描述类的单例的属性(方法降级为属性)
- 接口就是伴随对象的类型
- 语法糖:扩展函数(且像scala那样可以给泛型加扩展函数)
- 泛型支持structural的子类型限制
利用伴随对象放置成员方法和静态方法、利用扩展函数补充成员方法
//只包含属性、字段
struct NewsArticle{
var location: String
val author: String
}
//伴随对象
object NewsArticle{
//默认Self是NewsArticle?
//NewsArticle的成员方法
val summarize: Self.()->String = self.()->{
self.location=xxx
}
//NewsArticle的静态方法
val static_summarize: ()->String = ()->{}
}
利用泛型设计接口
//只包含属性、字段
struct NewsArticle {
var headline: String
get = it.()->{}
set = it.(value:String)->{ it = value}
var location: String
val author: String
val content: String
}
//用于接口
struct Summary<Self: type>{
//扩展方法式的写法
val summarize: Self.()->String
val summarize_author: Self.()->String = self.()->{}
}
//实现接口
object NewsArticle: Summary<Self = NewsAriticle> {
//NewsArticle的成员方法
val summarize: Self.()->String = self.()->{}
//NewsArticle的静态方法
val static_summarize: ()->String = ()->{}
}
object OneArticle: NewsArticle {
}
使用的时候,接口要求的是“某对象的类型的伴随对象”符合要求,而且需要把“某对象的类型”填入泛型参数里。
现在我觉得比较好的设计是:
val function= (t:(T:Summary<T>))->{}
val function= (t:_:Summary<_>)->{}
val function= (t::Summary)->{}
val function: (T:Summary<T>)->() = (t)->{}
接口可以直接要求属性字段
struct Summary<
Self: struct{
var location: String
val author: String
}
> {
val summarize: Self.()->String = self.()->{
self.location=xxx
}
}
struct NewsArticle{
var location: String
val author: String
}
object NewsArticle: Summary<Self = NewsArticle>{
}
附录
“某对象的类型的伴随对象”符合要求的思考
会出现下面这样抽象的东西:
val function= <T> ((t as T).type:Summary<T>)->{}
val function= <T> (t:T)->{} where T:Summary<T>
val function= <T:Summary<T>> (t:T)->{}
val function= (t:T:Summary<T>)->{}
如果直接从t出发,这里需要两个语法糖:
- 把对象的类型填入类型的泛型里,例如
t:T
要得到Summary<T>
。 写成Summary<t.type>
或者写成Summary<type>
? - 要求对象的类型的伴随对象的类型,例如
t:T
且T:Summary<T>
。 写成t.type : Summary<t.type>
或者写成t.type : Summary<type>
?
(类似于rust struct/trait/impl三件套)
rust的设计
trait专注方法的接口
struct专注字段
impl给struct提供方法
泛型用于struct的字段类型扩展,并且可以特设重载多态
pub trait Summary {
fn summarize(&self) -> String;
fn summarize_author(&self) -> String {
format!("(Read more from {}...)", self.summarize_author())
}
}
pub struct NewsArticle {
pub headline: String,
pub location: String,
pub author: String,
pub content: String,
}
impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!("{}, by {} ({})", self.headline, self.author, self.location)
}
}
pub struct Tweet {
pub username: String,
pub content: String,
pub reply: bool,
pub retweet: bool,
}
impl Summary for Tweet {
fn summarize(&self) -> String {
format!("{}: {}", self.username, self.content)
}
}
pub fn notify(item1: &impl Summary, item2: &impl Summary) {}
pub fn notify<T: Summary>(item1: &T, item2: &T) {}
pub fn notify<T: Summary + Display>(item: &T) {}
struct Pair<T> {
x: T,
y: T,
}
impl<T> Pair<T> {
fn new(x: T, y: T) -> Self {
Self { x, y }
}
}
impl<T: Display + PartialOrd> Pair<T> {
fn cmp_display(&self) {
if self.x >= self.y {
println!("The largest member is x = {}", self.x);
} else {
println!("The largest member is y = {}", self.y);
}
}
}