2014-12-02 159 views
1

我有两个类都实现了IFruit接口。简化的问题是我想在某些情况下用芒果代替苹果。但是下面的例子会导致编译器错误。打字稿对象转换错误

无法将'Mango'转换为'Apple':类型'Mango'和'Apple'将属性'_element'定义为私有。

为什么这是一个问题?界面中不显示_element。它不应该被迫公开。

​​

回答

2

有三种解决方案可以使用,选择是基于上下文的。

接口

因为私有成员有效地使它不可能对任何其他类型的在结构上一场比赛,你永远不能让一个Mango看起来像一个Apple。他们都完全满足IFruit接口,所以如果你是IFruit键入他们,他们是完全substituatble - 比如下面两个new Apple(e)new Mango(e)IFruit类型注释 - 虽然这与它的工作只是Apple,例如:

interface IFruit { 
    getElement(): HTMLElement; 
} 

class Apple implements IFruit { 

    private _element; 

    constructor(element: HTMLElement) { 
     this._element = element; 
    } 

    getElement(): HTMLElement { 
     return this._element; 
    } 
} 

class Mango implements IFruit { 

    private _element; 

    constructor(element: HTMLElement) { 
     this._element = element; 
    } 

    getElement(): HTMLElement { 
     return this._element; 
    } 

} 

var e: HTMLElement; 
var a: IFruit = new Apple(e); 
var m: IFruit = new Mango(e); 
a = m; 

继承

你也可以使用继承来解决这个问题。 AppleMango可以访问的基础上保护_elementFruit类:

class Fruit { 
    protected _element : HTMLElement; 

    constructor(element: HTMLElement) { 
     this._element = element; 
    } 

    getElement(): HTMLElement { 
     return this._element; 
    } 
} 

class Apple extends Fruit { 
    constructor(element: HTMLElement) { 
     super(element); 
    } 
} 

class Mango extends Fruit { 
    constructor(element: HTMLElement) { 
     super(element); 
    } 
} 

var e: HTMLElement; 
var a = new Apple(e); 
var m = new Mango(e); 
a = m; 

公共

如果你想让他们不使用界面还是继承兼容,你需要做的财产公开:

interface IFruit { 
    getElement(): HTMLElement; 
} 

class Apple implements IFruit { 

    public _element; 

    constructor(element: HTMLElement) { 
     this._element = element; 
    } 

    getElement(): HTMLElement { 
     return this._element; 
    } 
} 

class Mango implements IFruit { 

    public _element; 

    constructor(element: HTMLElement) { 
     this._element = element; 
    } 

    getElement(): HTMLElement { 
     return this._element; 
    } 

} 

var e: HTMLElement; 
var a = new Apple(e); 
var m = new Mango(e); 
a = m; 
+0

我去了第一个选项。但我仍然认为这很奇怪。如果两者都有相同的私人成员,那么它应该可以工作。如果“元素”是公共的而非私人的,它也可以工作。 – 2014-12-02 13:43:25

+2

这是结构分类系统的本质 - 如果要应用领域驱动设计,能够创建非匹配类型非常重要。例如'class CustomerId {constructor(private id:number){} getId(){return this.id; }}'不能被误认为'class ProductId {constructor(private id:number){} getId(){return this.id; }}'Playground上的示例:http://bit.ly/1FKUkxE – Fenton 2014-12-02 13:48:26

+0

上述评论中的代码示例很难阅读,但在此处更详细地写入:https://www.stevefenton.co.uk /内容/博客/日期/ 201412 /博客/为什么私营成员对结果的In-风雨同路,打字稿,结构/ – Fenton 2014-12-02 14:05:17