如何使用包装类等于Joshua Bloch描述的组合?(How is having a wrapper class equals composition as described Joshua Blo

编程入门 行业动态 更新时间:2024-10-22 19:23:34
如何使用包装类等于Joshua Bloch描述的组合?(How is having a wrapper class equals composition as described Joshua Bloch?)

我正在读Joshua Bloch撰写的有效java书。 在“赞成组合而不是继承”的第16项中,他给出了一个使用HashSet并查询自创建以来添加了多少元素的示例(不要与当前大小相混淆,当删除元素时该大小会下降)。 他提供了以下代码,这里是getAddCount返回6,我可以理解。 这实际上应该返回3。 (这是因为HashSet的addAll方法是在其add方法之上实现的)

import java.util.HashSet; public class InstrumentedHashSet<E> extends HashSet<E> { // The number of attempted element insertions private int addCount = 0; public InstrumentedHashSet() { } public InstrumentedHashSet(int initCap, float loadFactor) { super(initCap, loadFactor); } @Override public boolean add(E e) { addCount++; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); } public int getAddCount() { return addCount; } public static void main(String[] args) { InstrumentedHashSet<String> s = new InstrumentedHashSet<String>(); s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); System.out.println(s.getAddCount()); } }

现在,他解释了一种解决方法,使用包装类(组合和转发)。 这是我很难理解的地方。 他提供以下两个班级

public class ForwardingSet<E> implements Set<E> { private final Set<E> s; public ForwardingSet(Set<E> s) { this.s = s; } public void clear() { s.clear(); } public boolean contains(Object o) { return s.contains(o); } public boolean isEmpty() { return s.isEmpty(); } public int size() { return s.size(); } public Iterator<E> iterator() { return s.iterator(); } public boolean add(E e) { return s.add(e); } public boolean remove(Object o) { return s.remove(o); } public boolean containsAll(Collection<?> c) { return s.containsAll(c); } public boolean addAll(Collection<? extends E> c) { return s.addAll(c); } public boolean removeAll(Collection<?> c) { return s.removeAll(c); } public boolean retainAll(Collection<?> c) { return s.retainAll(c); } public Object[] toArray() { return s.toArray(); } public <T> T[] toArray(T[] a) { return s.toArray(a); } @Override public boolean equals(Object o) { return s.equals(o); } @Override public int hashCode() { return s.hashCode(); } @Override public String toString() { return s.toString(); } }

import java.util.*; public class InstrumentedSet<E> extends ForwardingSet<E> { private int addCount = 0; public InstrumentedSet(Set<E> s) { super(s); } @Override public boolean add(E e) { addCount++; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); } public int getAddCount() { return addCount; } public static void main(String[] args) { InstrumentedSet<String> s = new InstrumentedSet<String>( new HashSet<String>()); s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); System.out.println(s.getAddCount()); } }

这是怎么回事? 在main方法中,我创建了一个HashSet实例并使用addAll方法,我添加了list的所有元素。 但是HashSet调用它的addAll方法(后者又使用它的add方法),这应该与正确示例中的第一个相同,我应该得到6的值,但这给了我3。

I am reading the book effective java by Joshua Bloch. on the item 16 of "favor composition over inheritance", he gives an example of using HashSet and querying how many elements have been added since it was created(not to be confused with current size, which goes down when an element is removed). he provided the following code and here the getAddCount return 6, which I can understand. This should return 3 actually. (this is because HashSet's addAll method is implemented on top of its add method)

import java.util.HashSet; public class InstrumentedHashSet<E> extends HashSet<E> { // The number of attempted element insertions private int addCount = 0; public InstrumentedHashSet() { } public InstrumentedHashSet(int initCap, float loadFactor) { super(initCap, loadFactor); } @Override public boolean add(E e) { addCount++; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); } public int getAddCount() { return addCount; } public static void main(String[] args) { InstrumentedHashSet<String> s = new InstrumentedHashSet<String>(); s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); System.out.println(s.getAddCount()); } }

Now he explains a way to fix this, using wrapper classes (composition and forwarding). here is where I am having hard time to understand. he provides the following two classes

public class ForwardingSet<E> implements Set<E> { private final Set<E> s; public ForwardingSet(Set<E> s) { this.s = s; } public void clear() { s.clear(); } public boolean contains(Object o) { return s.contains(o); } public boolean isEmpty() { return s.isEmpty(); } public int size() { return s.size(); } public Iterator<E> iterator() { return s.iterator(); } public boolean add(E e) { return s.add(e); } public boolean remove(Object o) { return s.remove(o); } public boolean containsAll(Collection<?> c) { return s.containsAll(c); } public boolean addAll(Collection<? extends E> c) { return s.addAll(c); } public boolean removeAll(Collection<?> c) { return s.removeAll(c); } public boolean retainAll(Collection<?> c) { return s.retainAll(c); } public Object[] toArray() { return s.toArray(); } public <T> T[] toArray(T[] a) { return s.toArray(a); } @Override public boolean equals(Object o) { return s.equals(o); } @Override public int hashCode() { return s.hashCode(); } @Override public String toString() { return s.toString(); } }

AND

import java.util.*; public class InstrumentedSet<E> extends ForwardingSet<E> { private int addCount = 0; public InstrumentedSet(Set<E> s) { super(s); } @Override public boolean add(E e) { addCount++; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); } public int getAddCount() { return addCount; } public static void main(String[] args) { InstrumentedSet<String> s = new InstrumentedSet<String>( new HashSet<String>()); s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); System.out.println(s.getAddCount()); } }

how this works? In the main method, I create an instance of HashSet and using addAll method, I add all the elements of list. but the HashSet invokes its addAll method (which in turn uses its add method), which should be the same as in the first in correct example and I should get value of 6, however this gives me 3.

最满意答案

public class InstrumentedHashSet<E> extends HashSet<E> {

你直接添加到HashSet因为addAll()委托给超级实现

InstrumentedHashSet<String> s = new InstrumentedHashSet<String>(); s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); System.out.println(s.getAddCount());

addAll()内部调用add() ,由于多态性,它addAll()实现

@Override public boolean add(E e) { addCount++; return super.add(e); }

增加计数并打印6 (3 + 1 + 1 + 1)。

public class InstrumentedSet<E> extends ForwardingSet<E> {

你要加入

private final Set<E> s;

因为addAll()委托给它,所以

public static void main(String[] args) { InstrumentedSet<String> s = new InstrumentedSet<String>( new HashSet<String>()); s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); System.out.println(s.getAddCount()); }

并打印3 。 这里add()在Set<E> s上调用,而不是在你的实例上调用。

结论是,如果你继承,你需要了解副作用。 super方法调用是否在内部调用任何其他方法调用? 如果是这样,您需要采取适当的行动。

继承(从底部开始)

s.add() // s is your InstrumentedHashSet instance, because of polymorphism (inheritance), this adds to the count this.add() // this is the internal call inside the HashSet#addAll() super.addAll(...) // this calls the HashSet implementation of addAll which calls add() internally s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); // s is your InstrumentedHashSet instance

组成

this.add() // this is the internal call to add() inside the Set implementation s.addAll() // s is the Set<E> instance super.addAll(...) // this calls the ForwardingSet implementation of addAll() s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); // s is your InstrumentedSet instance

In

public class InstrumentedHashSet<E> extends HashSet<E> {

you're adding directly to the HashSet because the addAll() is delegating to the super implementation

InstrumentedHashSet<String> s = new InstrumentedHashSet<String>(); s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); System.out.println(s.getAddCount());

The addAll() internally calls add() which defers to your @Override implementation of add() because of polymorphism

@Override public boolean add(E e) { addCount++; return super.add(e); }

that increments the count and prints 6 (3 + 1 + 1 + 1).

In

public class InstrumentedSet<E> extends ForwardingSet<E> {

you are adding to

private final Set<E> s;

because the addAll() is delegating to it, so

public static void main(String[] args) { InstrumentedSet<String> s = new InstrumentedSet<String>( new HashSet<String>()); s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); System.out.println(s.getAddCount()); }

and prints 3. Here the add() is being called on the Set<E> s, not on your instance.

The conclusion is that if you are inheriting, you need to understand the side-effects. Do the super method calls invoke any other method calls internally? If so, you need to act appropriately.

Inheritance (start from bottom)

s.add() // s is your InstrumentedHashSet instance, because of polymorphism (inheritance), this adds to the count this.add() // this is the internal call inside the HashSet#addAll() super.addAll(...) // this calls the HashSet implementation of addAll which calls add() internally s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); // s is your InstrumentedHashSet instance

Composition

this.add() // this is the internal call to add() inside the Set implementation s.addAll() // s is the Set<E> instance super.addAll(...) // this calls the ForwardingSet implementation of addAll() s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); // s is your InstrumentedSet instance

更多推荐

本文发布于:2023-08-01 02:31:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1352874.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:组合   如何使用   Bloch   Joshua   composition

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!